I'm attempting to mock an abstract class, but from what I've seen, I don't think it's possible. We have some classes that use generics, that must extends a specific abstract class. There's a whole group of them and they have been mocked successfully. The abstract class has one method that deals with returning the generic and looks like this:
public abstract class ChildPresenter <T extends ChildView> {
private T view;
public abstract T getView();
}
The class we are testing has the following in it:
public class ParentPresenter {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
List<ChildPresenter> childPresenters;
}
In the constructor, these classes are injected in, using Google Guice, set to the variables, and added to the list of child presenters.
The method under test is one that iterates over all of the childPresenters objects and runs the method getView().
I attempted it this way in my test class:
public class ParentPresenterTest {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
private List<ChildPresenter> childPresenters;
//This is an abstract class
private ChildView childView;
#BeforeTest
public void createInjector() {
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
//e.g.
childPresenter1 = mock(ConcreteChildPresenter1.class);
binder.bind(ConcreteChildPresenter1.class).toInstance(childPresenter1);
//e.t.c for other variables
//Same for child view
childView = mock(ChildView.class);
binder.bind(ChildView.class).toInstance(childView);
}
childPresenters = new ArrayList<ChildPresenter>();
childPresenters.add(childPresenter1);
//Add all child presenters
for(ChildPresenter childPresenter : childPresenters) {
when(childPresenter.getView()).thenReturn(childView);
}
}
}
The problem happens at the line when(childPresenter.getView()).thenReturn(childView); as Mockito complains with the following message:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ChildView$$EnhancerByMockitoWithCGLIB$$2f6a4bd5
cannot be returned by getView() getView() should return ConcreteChildView1
*** If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because:
This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing.
A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Which I can understand, but it seems a waste to mock each individual concrete ChildView when all I want to do is confirm the mocked ChildView called a single method using the following:
verify(childView, atLeast(childPresenters.size())).getView();
Is there another way to do this? Can I somehow use mocked abstract classes in place of the concrete ones?
EDIT Here is a concrete version of how the getView() method is implemented:
public ConcreteChildPresenter1<ConreteChildView1> {
#Override
public ConreteChildView1 getView() {
view.buildView();
return view;
}
}
And the abstract ChildView class that all child views extend:
public abstract ChildView {
public abstract void buildView();
}
Since each child presenter returns a view of a specific type, you can't, as you already understood, substitute them with mocks of the abstract class ChildView.
There is a way to get at runtime the concrete type of ChildView only if you provide a proper implementation like explained here: Get generic type of class at runtime
Then you may initialize the presenters' mocks in this way:
for(ChildPresenter childPresenter : childPresenters) {
//this getter returns the needed runtime class
when(childPresenter.getView()).thenReturn(mock(childPresenter.getViewType()));
}
Based on the refinements, the mocked ChildView is based on the wrong superclass. I think you can fix it at Guice injector:
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
// ...
//Same for child view
childView = mock(ConcreteChildPresenter1.class); // this is the fix
binder.bind(ChildView.class).toInstance(childView);
}
Related
I have a super abstract class that has some common implemented methods and other abstract methods to be implemented by a subclass. One of the common implemented methods is a method to be annotated as #Scheduled, but I want the subclass to define how this schedule should be defined (fixed delay, fixed rate or cron .. etc). How to implement such behaviour ?
One approach I thought of is to override the method to be scheduled in the subclass such that it just call its corresponding method in the super class and add the #Scheduled on it with the desired definition, but I don't know how to enforce the subclass to do so as this method is not abstract.
Super Abstract Class
public abstract class SuperClass {
public abstract void x();
public void y() {
// Some implementation
}
// Method to be scheduled.
public void scheduledMethod() {
x();
y();
}
}
Subclass
public class Subclass extends SuperClass {
#Override
public void x() {
// Some implementation
}
// How to enforce the developer to add this ?
#Scheduled(cron = "0 0 0 * * ?")
public void scheduledMethod(){
super.scheduledMethod();
}
}
I couldn't get my head around how you could use #Scheduled but, I've an alternative:
In your abstract class, require a method to be implemented by subclasses to return the schedule:
public String getCronString();
Programmatically schedule the task using Scheduler using the method getCronString() that's implemented in your subclasses, to return the cron schedule. Few examples on how to programmatically schedule tasks with Spring boot:
https://www.baeldung.com/spring-task-scheduler
SO Question
Basically, if your subclasses are not implementing public String getCronString(); your code won't compile.
One option would be to check that the #Scheduled annotation is present (or meta-present) at bean creation time. This can be easily achieved using reflection in a #PostConstruct method on the superclass:
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
public abstract class SuperClass {
...
#PostConstruct
public void enforceScheduling() {
boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(getClass(), "scheduledMethod"), Scheduled.class) != null;
if (!annotationPresent) {
throw new IllegalStateException("#Scheduled annotation missing from scheduledMethod");
}
}
}
This will cause an exception to be thrown at application start-up time when Spring attempts to create the bean, failing fast and making it very obvious what is missing.
One thing I've done in the past in projects with constraints on a class hierarchy that I could not easily check at compile or runtime was to write a unit test that iterated through every concrete (non-abstract) instance of the class and checked whether it met that constraint.
Since this is using Spring, we probably care more that each bean of this type matches the constraint than whether each subclass on the classpath does.
The constraint in this case is that the #Scheduled annotation is present (or meta-present) on the given method in the subclass. The presence of the annotation can be easily achieved using reflection given the Class object of the subclass.
Putting this together, we can write a unit test utilizing this technique:
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
#SpringBootTest
public class SuperClassTest {
#Autowired
private List<SuperClass> beansOfThisType;
#Test
public void allBeansMustBeScheduled() {
for (SuperClass bean : beansOfThisType) {
boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(bean.getClass(), "scheduledMethod"), Scheduled.class) != null;
assertTrue(annotationPresent, "#Scheduled annotation missing from scheduledMethod for " + bean.getClass());
}
}
}
Checking every object of the type on the classpath rather than just the Spring beans would be a very similar approach; the difference would be the mechanism to get the list of Class objects to check. Getting the matching objects from the classpath is non-straightforward enough that it's outside the scope of this answer. How do you find all subclasses of a given class in Java? lists a number of ways to accomplish it.
I have a AbstractBaseRepository. All my Repositories extends from this class. I created another class RepositoryFactory to create any instance of Repository. Due to early binding of static method, I am facing problem.
public abstract class AbstractBaseRepository {
public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {
throw new RuntimeException("Override and provide valid initialization");
}
...
}
public class RepositoryFactory {
public static <T extends AbstractBaseRepository> T getRepository(Class<T> cls) {
return T.getNewInstance(entityManagerFactory);
}
...
}
an example subclass
public class DeviceModelRepo extends AbstractBaseRepository {
public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {
return new DeviceModelRepo(entityManagerFactory);
}
...
}
Whenever I call getRepository() with a valid subclass of AbstractBaseRepository, runtime exception is thrown. This is due to early binding of static methods. During compile time, getNewInstance gets bound with AbstractBaseRepository rather than at runtime with actual type of the class. Any good workarounds?
My first suggestion is using Spring. It is very easy to get a list of all beans created with a certain interface.
Also, if you think of your Repository instances as a type of "plug-in" you might see how Java's ServiceLoader class can help.
Also, another approach is to use a switch statement in the factory and create the instances for each case rather than using static methods on the Repository subclasses.
Finally, I don't recommend reflection solutions but there are ways to load the class based on its name and reflectively creating a new instance.
But overriding static methods is not possible.
What I have understood by seeing your code is that you want to have different implementations of AbstractBaseRepository such as DeviceModelRepo. Then you want a factory class to create the instance of specific implementation of AbstractBaseRepository. Here the major problem is you try to overriding static methods which can never be overwritten but subclass will hide the parent implementation. Please don't use static method for overriding. You can change your implementation as given below and this issue will be resolved.
public abstract class AbstractBaseRepository {
public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Then below implementation for subclass.
public class DeviceModelRepo extends AbstractBaseRepository {
public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Now I am providing you two implementation of factory class.
One is having different method for each of implementation, such as getDeviceModelRepository().
Another solution is to use reflection and get repository instance by passing the implementation repository class.
public class RepositoryFactory {
//Solution-1, create separate method for each of repository like below
public static AbstractBaseRepository getDeviceModelRepository() {
return new DeviceModelRepo(entityManagerFactory);
}
//Solution-2, use reflection to get instance of specific implementation
//of AbstractBaseRepository
public static <T extends AbstractBaseRepository> T
getRepository(Class<T> repoClass) throws Exception{
return repoClass.getConstructor(EntityManagerFactory.class)
.newInstance(entityManagerFactory);
}
...
}
With reflection solution, you can get the repository instance as given below.
RepositoryFactory.getRepository(DeviceModelRepo.class)
A)
Class Parent4{
private I18nUtils i18n;
//-----------Here Nullpointerexception occur----------------
public Parent4(){
SetText(i18n.getText("HELLO");
}
}
B)
Class Parent3 extends Parent4{
private I18nUtils i18n;
}
C)
Class ParentParent2 extends Parent3{
private I18nUtils i18n;
}
D)
Class Parent extends ParentParent2{
private I18nUtils i18n;
}
E)
Class Child extends Parent{
protected method_name(){
//.......DO Something......
}
}
My Test Class:
public testclass{
Class cls = Class.forName("Child");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("method_name",Null);
method.setAccessible(true);
method.invoke(obj, null);
So while creating object of child class it called and invoke all dependency of child class and initialize with mock object and called all parent class and its constructor.
While i18n is set null by default.
1) I tried to accessed with reflection. with the help superClass().getDeclared("i18n"). But eventually it only access to its preceding class only. So it not set the value for Parent5() class.
2) Also I have tried to direct access Parent5 class i18n field.
But when invoking the child class. It will create new instance and same as that it will reset parent5() class i18n as null.
I will answer following one of your comments.
Yes, calling another method instead of super and using a partial mock is a correct solution. EasyMock can't mock super.
Then, if you want to mock a method called by a constructor, that's indeed impossible. EasyMock doesn't provide a way to mock before having the mock.
In both cases, modifying the design will probably improve the design.
I probably handle this situation. I read the Easymock documentation. From there I got some similar case to handle this kind of situtation.
Code here:
Objenesis objenesis = new ObjenesisStd(); // or ObjenesisSerializer
child obj_1 = objenesis.newInstance(child.class);
Method method = obj_1.getClass().getDeclaredMethod("method_name",MessageReceiver.class);
method.setAccessible(true);
method.invoke(obj_1, null);
For my case it working fine. As such I did not able to mock parent field anywhere.
NOTE: I did not have any field dependency of parent class on my child class method. Only I need to mock the (i18n) field so it does not cause "nullpointerexception". But eventually I handle with objensis.
I've created some tests in Mockito for verifying that other presenters call specific methods during a main presenter's initialization. The other presenters have been mocked.
The mocked presenters all implement the following interface:
public interface PresenterHasParent<V, P extends Presenter> extends Presenter<V> {
public abstract void setParentPresenter(P presenter);
}
And the Presenter has the following setup:
public interface Presenter<V> {
V getView();
void initPresenter();
}
In my parent presenter class I have the following:
public class ParentPresenter() implements Presenter<ParentView>{
private ParentView view;
private ChildPresenterOne childPresenterOne;
private ChildPresenterTwo childPresenterTwo;
private ChildPresenterThree childPresenterThree;
private ChildPresenterFour childPresenterFour;
#Inject
public ParentPresenter(ParentView view, ChildPresenterOne childPresenterOne,
ChildPresenterTwo childPresenterTwo,
ChildPresenterThree childPresenterThree
ChildPresenterFour childPresenterFour) {
this.view = view;
this.childPresenterOne= childPresenterOne;
this.childPresenterTwo= childPresenterTwo;
this.childPresenterThree= childPresenterThree;
this.childPresenterFour= childPresenterFour;
}
//Other code
#Override
public void initPresenter() {
view.setPresenter(this);
childPresenterOne.initPresenter();
childPresenterTwo.initPresenter();
childPresenterThree.initPresenter();
childPresenterFour.initPresenter();
childPresenterOne.setParentPresenter(this);
childPresenterTwo.setParentPresenter(this);
childPresenterThree.setParentPresenter(this);
childPresenterFour.setParentPresenter(this);
registerHandlers();
}
}
As you can see, we're using Injection to allow for easy unit test. I then create my mocked instances like so:
public class ParentPresenterTest {
private List<PresenterHasParent> presenters;
private ChildPresenterOne childPresenterOne;
private ChildPresenterTwo childPresenterTwo;
private ChildPresenterThree childPresenterThree;
private ChildPresenterFour childPresenterFour;
private ParentPresenter parentPresenter;
private View view;
#BeforeTest
public void setUp() {
presenters = new ArrayList<PresenterHasParent>();
view = mock(View.class);
childPresenterOne= mock(ChildPresenterOne.class);
presenters.add(childPresenterOne);
childPresenterTwo= mock(ChildPresenterTwo.class);
presenters.add(childPresenterTwo);
childPresenterThree= mock(ChildPresenterThree.class);
presenters.add(childPresenterThree);
childPresenterFour= mock(ChildPresenterFour.class);
presenters.add(childPresenterFour);
parentPresenter = new ParentPresenter(view, childPresenterOne, childPresenterTwo, childPresenterThree, childPresenterFour);
}
#Test
public void testInitPresenter() {
parentPresenter.initPresenter();
verify(view).setPresenter(parentPresenter);
for(PresenterHasParent presenterToCheck : presenters) {
Reporter.log("Testing the presenter " + presenterToCheck.getClass().getName(), true);
verify(presenterToCheck).initPresenter();
verify(presenterToCheck).setParentPresenter(parentPresenter);
validateMockitoUsage();
Reporter.log("Successfully tested the presenter " + presenterToCheck.getClass().getName(), true);
}
}
}
Upon running these tests, I get a failure on the 3rd or 4th presenter (Depending on what I do) which is:
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at ParentPresenterTest.testInitPresenter(ParentPresenterTest.java:118)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of:
final/private/equals()/hashCode() methods. Those methods cannot be
stubbed/verified.
at
ParentPresenterTest.testInitPresenter(ParentPresenterTest.java:119)
Now if it failed consistently, I could understand, but if I put breakpoints in and step over each method, it works fine. If I put no breakpoints in, it always fails and complains about the line (118) that reads on the 3rd presenter: verify(presenterToCheck).setParentPresenter(presenter);
I don't understand why it's failing, especially since it does work if I debug and step over the code. Can anyone shed any light on this perplexing issue?
Edit
So if I step over the 3rd presenter verify check and then run the code again, it will fail on the 4th one with the same issue. But if I step over the code for the 4th one as well, it works fine. Something very odd is happening here and since I can't debug to find the issue, it's making life quite difficult!
After a bit of investigation, I found the issue. Due to the way I had created some super abstract classes (Before I had created the new interface), I was causing Mockito to get confused. It was a bit of bad design, but also Mockito behaving oddly.
The method that I was checking:
verify(presenterToCheck).setParentPresenter(parentPresenter);
Was an abstract method in the interface PresenterHasParent. However the objects that failed the test also implemented a BaseEditPresenter. This BaseEditPresenter didn't implement the interface PresenterHasParent but had their own version of the method setParentPresenter(). This was causing confusion with Mockito as it didn't know what method was truly called (Even though they did the same thing). It was strange though that it did work on step over, but never when the code was directly ran.
So to fix it, I had to clean up the design and make sure that the BaseEditPresenter had implemented the PresenterHasParent interface and not it's subclasses of ChildPresenterThree and ChildPresenterFour.
I'm readin http://xunitpatterns.com/Test%20Stub.html and have some questions about the use of stubs, for example, in the code shown on the page the author creates a class called TimeProviderTestStub.java for use in test code. I have some doubts about this line in the test code:
TimeDisplay sut = new TimeDisplay();
// Test Double installation
sut.setTimeProvider(tpStub);
Do I need modify my class(SUT) to recieve one object TimeProviderTestSub?
Both the stub and the real class are supposed to implement some interface, i.e. ITimeProvider, and setTimeProvider() should take this interface as its parameter. The interface must expose all methods that the SUT needs to interact with the object, since TimeDisplay can now only use the object through the ITimeProvider interface (which allows us to use a stub instead of the real object in our tests).
In the example, the SUT (TimeDisplay) seems to only need the getTime() method, so the interface should only contain that method:
public interface ITimeProvider {
Calendar getTime();
}
The declaration of the stub should be
public class TimeProviderTestStub implements ITimeProvider { ... }
and the declaration of the real class should be
public class TimeProvider implements ITimeProvider { ... }
Finally, the SUT must change its setter method to accept the interface:
public void setTimeProvider(ITimeProvider timeProvider) { ... }
and also change its internal timeProvider field to be of the type ITimeProvider.
If you do not control the code of the real class (so that you cannot make it implement the interface), you can create an adapter class which wraps the real class and implements the interface.