Inject mocks in mocked abstract class - java

I have an abstract class which contains logic in concrete methods:
public abstract class AbstractEventHandler implements EventHandler {
private final Dependency dependency;
public AbstractEventHandler(Dependency dependency) {
this.dependency = dependency;
}
#Override
void handleEvent(Event event) {
dependency.doSomeWork();
[...]
doHandleEvent(event);
[...]
}
#Override
void handleOtherEvent(OtherEvent otherEvent) {
dependency.doOtherWork();
[...]
doHandleOtherEvent(event);
[...]
}
protected abstract doHandleEvent(event);
protected abstract doHandleOtherEvent(event);
}
Explored solutions to test my abstract class:
create a dummy implementation of the abstract class (good point for constructors Mocking an abstract class and injecting classes with Mockito annotations?)
test the handleEvent(event) logic in concrete classes but I would have to duplicate the test in every concrete classes (or once, but in which class?)
use PowerMock...
use Mockito to instantiate an implementation of the abstract class and call real methods to test logic in concrete methods
I chose the Mockito solution since it's quick and short (especially if the abstract class contains a lot of abstract methods).
#ExtendWith(MockitoExtension.class)
class AbstractEventHandlerTests {
#Mock
private Dependency dependency;
#InjectMocks
#Mock(answer = Answers.CALLS_REAL_METHODS)
private AbstractEventHandler abstractEventHandler;
Since #InjectMocks is not permitted on a field already annotated with #Mock, how can I inject mocked dependencies in my abstract class?

To reply to comments, I initially wanted to test the behavior of the concrete method in the abstract class because this method has to do some work (using the provided dependency), before calling implementations. To test this behavior, I either had to write tests in each implementation (can have a lot of implementations) or to test it once via the abstract class.
I ended up using the first solution: create an anonymous inner class as an implementation of the abstract class. Thanks.

Related

Y it's not mendatory to implement all interface methods in Child abstract class But Mendatory to implement all Interface methods in Grand Child class?

I made an interface as:
interface Castle
{
public void sad();
public void cool();
}
Then i made a child abstract class of it as:
abstract class Castle2 implements Castle
{
abstract void sad();
}
Here I left the implementation of cool(), and if i complile the above code, it compiled Successfully
But when i added 1 more sub class of Castle2 as:
class Castle3 extends Castle2{
public void sad(){
System.out.println("SAD");
}
public static void main(String...args){
new Castle3().sad();
}
}
And tried to compile the above code then it is not even compiling my code stating the following error
Castle.java:13: error: Castle3 is not abstract and does not override abstract method cool() in Castle
When i run javap tool on class Castle2, then i got the following result
abstract class Castle2 implements Castle {
Castle2();
public void sad();
}
Why Compiler is Forcing me to implement a interface Castle's method in class Castle3 which is not even present in class Castle2?
And Why Compiler is not Forcing me to implement a interface Castle's method in class Castle2?
That is because a concrete class must have implementation because they can be instantiated. Suppose they allow concrete class not to implement all the methods of an interface, there will arise a problem. If in the code we call the unimplemented method, JVM wont be having the address of the unimplemented method.
But abstract classes can not be instantiated. Thats why it is not mandatory to implement methods of an interface by an abstract class.
Because we cannot create object of abstract class. But if abstract class has a subclass, this subclass can be instantiated.
Thats why we need implement all methods in subclass

Is it more optimal from maintenance point of view to implement property injection vs constructor injection?

Let's say I have the following classes and dagger module
public class Base implements IBase {
private IDependency dependency; //IDependency is an interface
Base(IDependency dependency) {
this.dependency = dependency
}
}
public class SubClass extends Base implements ISubclass {
Base(IDependency dependency) {
super(dependency)
}
}
#Module
public class MyModule {
// Let's assume some other class use SubClass and requires this
#Provides
ISubclass providesSubclass(IDependency dependency) {
return new SubClass(dependency);
}
}
If I add a new parameter to Base constructor, I'll have to go to MyModule and modify provides method to include this new parameter (besides obviusly chaging Base and Subclass constuctors). It seems to me that using propery injection I don't have this problem since I'm not using any constructor.
My feeling is that I might be doing something wrong or I have some concept wrong. I prefer constructor injection over property injection but right now I have to add a constructor parameter to a base class used by 40 other classes and not only I have to modify those 40 classes constructors, I also have to modify modules to reflect new constructors parameters.
Am I missing something? Am I correct if I say that doing constructor injection I'll write much more less code and maintenance will be easier?
Yes, you are missing some awesome feature: You can still use constructor injection in this case! And you don't even have to write it yourself.
If all of the dependencies can be provided, dagger can and will create the object for you. Given that you can provide IDependency you just need to modify your code like the following:
public class SubClass extends Base implements ISubclass {
#Inject // Don't forget the annotation!
public Base(IDependency dependency) {
super(dependency)
}
}
#Module
public class MyModule {
#Provides
ISubclass providesSubclass(SubClass subclass) {
return subclass;
}
}
You provide the interface, yet you depend on your implementation to provide it. Dagger will resolve this, and you can merrily add as many parameters to the constructor as you like. (Apart from the obvious changes to the actual constructors you already pointed out)
Don't forget the #Inject annotation!

Spring autowire multiple service Implementations

I have one base interface and two implementations
public interface AnimalService
{
public void eat();
}
#Service("animalService")
#Transactional
public class AnimalServiceImpl implements AnimalService
{
#Override
public void eat()
{
System.out.println("i'm eating");
}
}
#Service("birdService")
#Transactional
public class BirdServiceImpl extends AnimalServiceImpl
{
public void fly()
{
System.out.println("i'm flying");
}
}
In my main method try to call this two service implementation in this way:
public class test
{
#Autowired
private AnimalService animalService;
#Autowired
#Qualifier("birdService")
private AnimalService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
This will give compilation error, since birdService can't find method fly(). Then I thought maybe the reason is i autowire AnimalService instead of BirdServiceImpl, So i change my autowire code from this:
#Autowired
#Qualifier("birdService")
private AnimalService birdService;
change to :
#Autowired
private BirdServiceImpl birdService;
But this will give me a runtime error, which is "can't find bean BirdServiceImpl".
I have google a lot of document, some say use #Resource. But this doesn't work for me. Some say register the bean in Spring Context, while all my bean registration is done by annotation. I don't want to touch Spring Context.
Now My solution is to add a new interface
public interface BirdService extends AnimalService
{
public void fly();
}
And let my BirdServiceImpl to implement this interface
public class BirdServiceImpl extends AnimalServiceImpl extends BirdService
{
public void fly()
{
System.out.println("i'm flying");
}
}
And my main class change to this:
public class test
{
#Autowired
private AnimalService animalService;
#Autowired
private BirdService birdService;
public static void main(String[] args)
{
animalService.eat();
birdService.eat();
birdService.fly();
}
}
Now is ok . But for me, this is not perfect. If I use plain java, i can just write single interface and multiple implementation. In the main method I can choose which implementation to use. Why in spring, i have to build a new interface for each new implementation in order to let my program run.
I want to know is there any better approach for my scenario?
In your question you are actually exposing two issues:
1. Inheritance issue
This problem doesn't depends on Spring Framework, but is due by your misconception about inheritance.
If you declare your service as AnimalService, you obviously can use it only as an AnimalService, regardless its real implementation.
If you want to use concrete implementations methods, you need to cast your object.
2. 'Autowiring a class' issue
This should normally work in Spring, so if your code doesn't work depends on your context configuration. Maybe you are also using AOP or transactions in your app,
If so, an autoproxy generator is enabled. This could cause your problem.
Take a look at this question: Spring Autowiring class vs. interface?. And note that:
When using autoproxies, you need to program to the interface, not the implementation
3. Just a note
How can you use () at the end of a Java interface/class name?
As I read in your question, you have already fixed the problem by creating an Interface for the inherited class BirdService. You only complain because you have to create a new Interface...
When I read your question, another question comes to mind: Which AOP are you using? Perhaps you have to add the CGLIB to your classpath (or Maven POM or Gradle).
Reading some of the Spring AOP documentation, I found this:
If the class of a target object that is to be proxied (hereafter
simply referred to as the target class) doesn’t implement any
interfaces, then a CGLIB-based proxy will be created. This is the
easiest scenario, because JDK proxies are interface based, and no
interfaces means JDK proxying isn’t even possible.

Calling Abstract classes #Activate method (apache felix)

I have an abstract class that a child class extends. My abstract class has an #Activate method, so does the child class. When OSGi creates my service, it invokes the child class activate method but never the abstract class's activate. Is there any way to force the abstract class's activate to be called by OSGi rather than having the child class manually call the parent activate method?
Here is some code to help elaborate on what I am asking.
#Component(componentAbstract=true, inherit=true)
#Service(value=ISomeInterface)
public abstract class AbstractHello implements ISomeInterface{
#Activate
public void activate(){
System.out.print("Hello ");
}
}
#Component
#Service(Value=ISomeInterface)
public class World extends AbstractHello{
#Activate
public void activate(){
System.out.println("World!");
}
}
The result of the code above would be "World!", rather than "Hello World!".
Initially I thought maybe the child activate method name was clobbering the abstract activate method of the same name. The result is the same even if the abstract class's activate method is given a unique name. Is there any way to have OSGi call the abstract class's activate method for me?
The DS annotation processors only look at the concrete class decorated with #Component. Super classes are not examined. Since the annotation processing is done at build time, super types may come from imported packages which are not chosen until runtime.
Also, the annotation processor generates component description XML from the annotations. So there can only be one activate="methodName" attribute in the XML. If you need the superclass' method called, then you need to call it from the subclass' method.
This has nothing to do with Apache Felix and OSGi, this is caused by poor understanding of Class Inheritance and Method Overriding in Java.
Your World class extends AbstractHello class and overrides its activate() method. If you want the AbstractHello.activate() method to be called then you must call it in
// Annotations excluded for readability.
public class World extends AbstractHello {
public void activate() {
super.activate();
System.out.println("World!");
}
}
OSGi can't help here.
UPDATE
Since the base class is abstract, and you don't have an instance of it, you can't call its method. Neither can OSGi container.

suppress a singleton constructor in java with powermock

I'm trying to unit-test some classes that make use of a Singleton class whose constructor does some things I can't (and shouldn't) do from the unit-test environment. My ideal scenario would be to end up with the constructor completely suppressed and then stub out the other member methods that my test classes invoke. My problem is that I can't seem to get the constructor suppressed.
My understanding of a way to solve this would be something like the following:
public class MySingleton extends AbstractSingletonParent {
public final static MySingleton Only = new MySingleton();
private MySingleton(){
super(someVar); // I want the super-class constructor to not be called
//
//more code I want to avoid
}
public Object stubbedMethod() {}
}
public class ClassToBeTested {
public void SomeMethod(){
Object o = MySingleton.Only.stubbedMethod();
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(MySingleton.class)
public class TestClass {
#Test
public void SomeTest() {
suppress(constructor(MySingleton.class));
mockStatic(MySingleton.class);
PowerMock.replay(MySingleton.class);
// invoke ClassToBeTested, etc
PowerMock.verify(MySingleton.class);
//make some assertions
}
}
Unfortunately during the createMock invocation, the MySingleton constructor is hit, and it still calls the super constructor.
Am I doing something silly? I found an example on the web doing almost exactly this, but it was using a deprecated suppressConstructor method. Despite the deprecation I tried that, too, to no avail...
Is what I'm trying to do possible? If so, what am I doing wrong?
*Edited version now works.
You need to annotate TestClass with the #PrepareForTest annotation so it has a chance to manipulate the bytecode of the singletons.
Also, the superclass ctor supression signature should include somevar's class; right now you're just suppressing the default ctor.
See the #PrepareForTest API docs. Here's a blog post with some more details as well.
FWIW, it's working for me:
#RunWith(PowerMockRunner.class)
#PrepareForTest({EvilBase.class, NicerSingleton.class})
public class TestEvil {
#Test
public void testEvil() {
suppress(constructor(EvilBase.class));
assertEquals(69, EvilBase.getInstance().theMethod());
}
#Test
public void testNice() {
suppress(constructor(EvilBase.class));
suppress(constructor(NicerSingleton.class));
assertEquals(42, NicerSingleton.getInstance().theMethod());
}
}
How about you set the instance field ('only' in your code) of your Singleton with an instance instantiated with the constructor you want (you can do all of this with the Reflection API or dp4j).
The motivating example of a dp4j publication discusses that.
I am not sure what is it that you are doing wrong. But on the design side, i can suggest you look into dependency injection i.e. DI.
For making your code testable, make use of DI. With DI you would pass the singleton class as an constructor argument to your test class. And now since you pass an argument, inside your test case you can create a custom implementation of the AbstractSingleton class and your test case should work fine.
With DI, your code will become more testable.

Categories