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.
Related
I'm using PowerMock to mock a java.net.Inet4Address (amongst other things) to return a particular IP address (getHostAddress()), as well as whether or not it's loopback (isLoopbackAddress()). I find that if I perform the actual stubbing (PowerMock.doReturn(...).when(mock).methodToStub()) anywhere other than from within the test class or an immediately inner class I get an UnfinishedStubbingException.
The problem is most obvious if I try to perform two stubs. The first one passes without an exception, but the second one throws the exception because it thinks the first one was not finished. If I only perform the one stub then I see different errors depending on what I do after that, so it's definitely the first stub that's causing the problem.
Below is some code that demonstrates the problem.
TestClass.java
/* package, imports... */
#RunWith(PowerMockRunner.class)
#PrepareForTest({Inet4Address.class})
public class TestClass {
#Test
public void test() {
Inet4Address mocked = PowerMockito.mock(Inet4Address.class);
// Option 1: Do it from within this class - WORKS
doStubbing(mocked);
// Option 2: Do it from an inner class - WORKS
Inner.doStubbing(mocked);
// Option 3: Do it from an inner class of the inner class - FAILS
Inner.Deeper.doStubbing(mocked);
// Option 4: Do it from an entirely different class - FAILS
OtherClass.doStubbing(mocked);
}
private void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
public static class Inner {
static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
public static class Deeper {
static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
}
}
}
OtherClass.java
/* package, imports... */
public class OtherClass {
public static void doStubbing(Inet4Address mocked) {
PowerMockito.doReturn(true).when(mocked).isLoopbackAddress();
PowerMockito.doReturn("127.0.0.1").when(mocked).getHostAddress();
}
}
I've put the creation of the mock at the start, common to all scenarios. It makes no difference if the mock is created from within the same class where the stubbing is being done. I've also made the methods static for ease of reading; the behaviour is the same if the classes are instantiated first.
I know there are workarounds so I can get my test working (perform the mocking right there in the test class, mock the InetAddress interface instead of the IPv4 implementation, etc) but I'd like to know why PowerMock is behaving in this way. I could almost understand it if it only worked from within the test class, but why does it work in an inner class as well?
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);
}
My question is about testing a class that implements many interfaces. For example, I have this class:
public class ServiceControllerImpl extends ServiceController implements IDataChanged, IEventChanged {
}
Now there are two ways for testing. The first is testing directly on the concrete class. That means the object type is the concrete class rather than the interface.
public class ServiceControllerImplTest {
ServiceControllerImpl instance;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
// you can bring this instance anywhere
}
}
The second way is testing on the interface only. We must typecast this object to all interfaces it implements.
public class ServiceControllerImplTest {
ServiceController instance; // use interface here
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
dataChangeListener = (IDataChanged) instance;
// instance and dataChangeListener "look like" two different object.
}
}
I prefer the second solution because maybe in future we can change the interface it implements to other objects, so using the concrete class might lead to failing tests in the future. I don't know the best practice for this problem.
Thanks :)
I prefer second solution because in reality, maybe in future we can change the interface it implements to other objects, so force using concreted class maybe leads to fail test in the future.
I guess it will lead to failed tests anyway, because you usually test that assertions are true or false. The question is: Do that tests apply to any IDataChanged or do these assertions only apply to the ServiceControllerImpl?
If the assertions only apply to the ServiceControllerImpl it doesn't matter if you use an IDataChanged instead of an ServiceControllerImpl, because you must edit the test when you use another IDataChanged object - different assertions. The test will fail if you use another object.
The way you setup unit tests Itself gives you an answer. A unit test usually tests one class in isolation. This means that you mock the environment. But mocking the environment means that you know the dependencies of the class you test and this are implementation details. So your test is written on an implemtation basis rather than only the interface.
It's possible to write tests that only test an abstract api - like an interface. But this usually means that your tests are abstract too. E.g.
public abstract class SetTest {
#Test
public void addAlreadyExistentObject(){
Set<String> setUnderTest = createSetUnderTest();
Assert.assertTrue(setUnderTest.isEmpty());
boolean setChanged = setUnderTest.add("Hello");
Assert.assertTrue(setChanged);
setChanged = setUnderTest.add("Hello");
Assert.assertFalse(setChanged);
Assert.assertEquals(setUnderTest.size(), 1);
}
protected abstract Set<String> createSetUnderTest();
}
You can then extend these abstract tests to test the api for concrete classes. E.g.
public class HashSetTest extends SetTest {
#Override
protected Set<String> createSetUnderTest() {
return new HashSet<String>();
}
}
In this case you can replace the implementation and the test must remain green.
But here is another example of an abstract api when replacing the object under test does not really make sense.
What about writing a test for all Runnables?
public class RunnableTest {
#Test
public void run(){
Runnable runnable = ...;
// What to test here?
// run is invoked without throwing any runtime exceptions?
runnable.run();
}
}
As you can see it does not make sense in some cases to write tests in a way so that you can easily replace the object under test.
If an api like the Set api defines a concrete state handling you can write abstract tests that test this.
JayC667 already correctly answered that it's best to refer to a class through its supertype(s) in tests of methods defined by those types. But I'd change the way you did that a bit to avoid casting:
public class ServiceControllerImplTest {
ServiceController controller;
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
controller = instance;
dataChangeListener = instance;
}
}
I am writing an integration test using mockito.
The unit under test is connected to a mocked object (objA) through an interface. The functionality that I am trying to mimic happens when the mocked objected fires an event and the unit under test is listening to it.
The interface:
public interface MyInterfaceAPI{
void fireyMyEvent(String msg);
}
The unit under test:
public class UnitUnderTest{
ObjA objA;
public UnitUnderTest(ObjA objA_t) {
objA = objA_t;
objA.addMyListener(new addMyHandler());
}
class addMyHandler implements MyInterfaceAPI{
#Override
public void fireyMyEvent(String msg) {
System.out.println(msg);
};
};
};
The test:
public class MyTest {
#org.junit.Test
public void run() {
ObjA mockObjA = mock(ObjA .class);
UnitUnderTest spyController = Mockito.spy(new UnitUnderTest());
MyInterfaceAPI mo2uut= mock(MyInterfaceAPI.class);
mo2uut.fireyMyEvent("hello from test");
}
}
My question is in the test, how do I connect the mo2uut ('mocked object' to 'unit under test') to the addMyHandler class implementation of MyInterfaceAPI inside the UnitUnderTest?
I am clearly missing something, but I am not sure what.
You have 2 schools on unit testing: The London / Mockist school, and the Detroit school.
If you want to use mocks, you must use dependency injection, so you can replace the dependencies with mocks. I think most people following the Detroit school would agree on this too, just because using dependency injection "is a good thing" (tm).
What you can do is to pass an instance of ObjA to UnitUnderTest in the constructor; Or alternatively (if ObjA is a collection) add the method UnitUnderTest.addListener(), where you pass an instance of a handler. With these 2 approaches, you'll be injecting a handler.
About using powermock: Powermock is a beast better used on old projects that have very little unit testing and their dependencies are a mess. If you are coding this now, using power mock is wrong (in the spirit of fairness, this is a biased idea, but it's shared with many other people).
Edit
Now I get your question! And I think that you're trying to test too much in one unit test and that causes the problem. Again, the mockist school talks about testing interactions... that's the key point. So in the test for UnitUnderTest the only interaction is with ObjA to set the handler, and that's the end of the story.
You'll probably have another test for ObjA to ensure that all handlers are invoked.
Now the last bit is how to test the code of the handler. But before that, please appreciate how independent each test is, as you're testing the interactions (and any logic in the code), but not more than 1 thing.
About the handler... you might not like this, but you have to make that class accessible, either make it public or extract it to another public class. If you extract it, you can put in an internal package so it's clear that the class shouldn't be used by anyone else.
If you have an hour to spare, I would suggest you to watch this great presentation: The Deep Synergy Between Testability and Good Design by Michael Feathers where he goes into a similar example of what you have in your code and why it makes sense to separate it.
Use PowerMock's PowerMockito to intercept the call to the addMyHandler class injecting a mock of MyInterfaceAPI as explained in Ben Kiefer's tutorial on "PowerMockito: Constructor Mocking"
I have managed to make it working. Posting here the fixed code for people who see this in the future.
public interface MyInterfaceAPI{
void fireyMyEvent(String msg);
}
The unit under test:
public class UnitUnderTest{
private ObjA objA;
public MyInterfaceAPI interfaceHandler;
public UnitUnderTest(ObjA objA_t) {
objA = objA_t;
interfaceHandler = new addMyHandler();
objA.addMyListener(interfaceHandler);
}
class addMyHandler implements MyInterfaceAPI{
#Override
public void fireyMyEvent(String msg) {
System.out.println(msg);
};
};
};
The test:
public class MyTest {
#org.junit.Test
public void run() {
ObjA mockObjA = mock(ObjA .class);
UnitUnderTest spyController = Mockito.spy(new UnitUnderTest());
spyController.hnd.fireyMyEvent("hello from test");
}
}
I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.
class Activity{
public void firstMethod(){
String str = secondMethod();
}
public String secondMethod(){
String str = null;
/* some Code */
return str;
}
}
Getting exception :
*org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!*
in the below code
class ActivityTest(){
Activity act;
#Before
public void setup(){
act = new Activity();
}
#Test
public void testFirstMethod(){
Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?
I found this post:
Mockito Spy'ing on the object being unit tested
However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.
I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.
As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.
Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.
class ActivityTest() {
Activity act;
#Before
public void setup(){
act = Mockito.spy(new Activity()); // Here!
}
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:
#RunWith(MockitoJUnitRunner.class)
class ActivityTest() {
#Spy
Activity act = new Activity();
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.
public class ActivityTest() {
private Activity act = new Activity();
#Test
public void testSecondMethod(){
assertEquals("expected-value", act.secondMethod());
}
#Test
public void testFirstMethod() {
act.firstMethod();
// success if no exception occurs
}
}
Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.
I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...
Here are some hints:
Mock the Activity.
Tweak the behavior of secondMethod with when / then / doReturn
Use doCallRealMethod when firstMethod is invoked.
Hope it helps.