Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count indirect method calls Mockito

I'm having problems with counting method calls with Mockito. Problem is that the method whos calls I want to count is called in test class indirectly by other method. Here is the code:

public class ClassForTest {
    private Integer value;

    public void doSmth() {
        prepareValue("First call");
        prepareValue("Second call");
        prepareValue("Third call");
        System.out.println(value);
    }

    protected void prepareValue(String msg) {
        System.out.println("This is message: " + msg);
        value++;
    }
}

And the test class:

public class ClassForTestTest extends TestCase {
    @Test
    public void testDoSmth() {
        ClassForTest testMock = mock(ClassForTest.class);
        doNothing().when(testMock).prepareValue(anyString());
        testMock.doSmth();
        verify(testMock, times(3)).prepareValue(anyString());
    }
}

Having such exception:

Wanted but not invoked:
classForTest.prepareValue(<any>);
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:24)

However, there were other interactions with this mock:
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:21)

Any ideas please. Thanks in advance!

like image 518
catdog Avatar asked Oct 20 '11 00:10

catdog


2 Answers

This will work. Using a spy calls the underlying method. Make sure value is initialized first.

    @Test
    public void testDoSmth() {
        ClassForTest testMock = spy(new ClassForTest());
        testMock.doSmth();
        verify(testMock, times(3)).prepareValue(anyString());
    }

    public class ClassForTest {
        private Integer value = 0;

        public void doSmth() {
            prepareValue("First call");
            prepareValue("Second call");
            prepareValue("Third call");
            System.out.println(value);
        }

        protected void prepareValue(String msg) {
            System.out.println("This is message: " + msg);
            value++;
        }
    }
like image 108
Garrett Hall Avatar answered Nov 11 '22 08:11

Garrett Hall


This is an indication that you need some refactoring to improve your design. A single class should be fully testable without needing to mock out pieces of it. Whatever pieces you feel need to be mocked out should be extracted into one or more collaborating objects. Don't fall into the trap of partial mocks. Listen to what the tests are telling you. Your future self will thank you.

like image 32
Ryan Stewart Avatar answered Nov 11 '22 09:11

Ryan Stewart