2

I need to test a few very simple classes. The first one is Child class:

public class Child extends Parent {

    public int newMethod() {
        anotherMethod();
        protectedMethod();
        return protectedMethodWithIntAsResult();
    }

    public void anotherMethod() {
        // method body no so important
    }
}

Than I have a Parent class:

public class Parent {
    protected void protectedMethod() {
        throw new RuntimeException("This method shouldn't be executed in child class!");
    }

    protected int protectedMethodWithIntAsResult() {
        throw new RuntimeException("This method shouldn't be executed in child class!");
    }
}

And finally my test class with single test method:

@PrepareForTest({Child.class, Parent.class})
public class ChildTest extends PowerMockTestCase {

    @Test
    public void test() throws Exception {

        /** Given **/
        Child childSpy = PowerMockito.spy(new Child());
        PowerMockito.doNothing().when(childSpy, "protectedMethod");
        PowerMockito.doReturn(100500).when(childSpy, "protectedMethodWithIntAsResult");

        /** When **/
        int retrieved = childSpy.newMethod();

        /** Than **/
        Assert.assertTrue(retrieved == 100500);
        Mockito.verify(childSpy, times(1)).protectedMethod();
        Mockito.verify(childSpy, times(1)).protectedMethodWithIntAsResult();
        Mockito.verify(childSpy, times(1)).anotherMethod(); // but method was invoked 3 times.
    }
}

I have a problem with last verification. Program throws an exception:

org.mockito.exceptions.verification.TooManyActualInvocations: 
child.anotherMethod();
Wanted 1 time:
-> at my.project.ChildTest.test(ChildTest.java:30)
But was 3 times. Undesired invocation:

And I don't understand why. Any ideas why it happens?

barbara
  • 3,111
  • 6
  • 30
  • 58
  • I would suggest that mocking method calls within the class under test is not a good testing practice. You should simply verify the expected result and any potential side-effects. – John B Aug 15 '14 at 15:55
  • Which line of your test is `30`? – John B Aug 15 '14 at 15:55
  • `Mockito.verify(childSpy, times(1)).anotherMethod();` – barbara Aug 15 '14 at 18:50
  • Try putting system outs in `anotherMethod` and after each method of the test. This should give you a clue as to when / how `anotherMethod` is being called. Let us know the result. – John B Aug 15 '14 at 19:13
  • Actually anotherMethod() was invoked successfully. And it printed a message only once. – barbara Aug 15 '14 at 19:19

1 Answers1

-1

The problem is happening when you call int retrieved = childSpy.newMethod() because in there you are calling anotherMethod() and protectedMethod().

Mockito assumes that you will be calling each method only ones but newMethod internally calls protectedMethod and anotherMethod and anotherMethod has already been called once.

If you remove the call to either newMethod or anotherMethod the test will run fine.

Vinay Pandey
  • 1,129
  • 3
  • 16
  • 33
  • where has `anotherMethod` been called once? The method under test invoked 3 other methods. The test verifies that each of these methods was invoked once. Are you suggesting that the code under test should be changed to make the test pass? Test must pass `newMethod` as that is the method under test and test does not call `anotherMethod`. – John B Aug 15 '14 at 19:10
  • Test does call `anotherMethod` as well as `newMethod` please look at the test code. – Vinay Pandey Aug 15 '14 at 19:11
  • Actually, it calls `Mockito.verify().anotherMethod` which is how to verify a call on a mock. – John B Aug 15 '14 at 19:14
  • When `childSpy.newMethod()` is called from test, then `newMethod` internals calls `anotherMethod` which gets mocked by Mockito. Now `anotherMethod` has already been mocked, that is why Mockito is complaining when it gets called again in the last line. – Vinay Pandey Aug 15 '14 at 19:17
  • Where do you see that `anotherMethod` has been mocked? I only see mocking (actually stubbing since this is a spy) of `protectedMethod` and `protectedMethodWithIntAsResult`. – John B Aug 15 '14 at 19:23
  • The last line `Mockito.verify(childSpy, times(1)).anotherMethod(); // but method was invoked 3 times.` – Vinay Pandey Aug 15 '14 at 19:25
  • I would put it this way. The method under test invokes `anotherMethod`. The test needs to verify that `anotherTest` was invoked exactly once when `newMethod` was invoked. How would YOU change the verification to work correctly? You cannot change the method under test and you much verify the invocation of `anotherMethod` exactly once. – John B Aug 15 '14 at 19:46