Mike
Mike

Reputation: 832

Mockito spy not mocking internal call to mocked method

I have a class that calls out to a third party system to get data that I want to mock using Mockito. Here is some pseudo-code of how my class is setup.

// class I will be spying
public class SomeService {
    // method I want to full test
    public List<String> methodA(List<String> list) {
        ... omitted code ...
        // internal call to method in the same class that will be mocked
        innerList = methodB(list);
        ... omitted code ...
    }

    // method that I want to mock/spy
    public List<String> methodB(List<String> list) {
        //details omitted since it should be mocked any never called
    }
}

Here is my test code. I setup my spy in a BeforeEach method to make sure that Mock is configured. When I directly call the mocked method, everything works as expected. When I call

public class SomeServiceTest{

    private SomeService service;

    @BeforeEach
    public void init() {
        service = Mockito.spy(SomeService.class);
        // also tried with creating a new object but has same failure conditions
        //service = Mockito.spy(new SomeService());

        // mocking methodB with answer details omitted to reduce clutter
        Mockito.doAnswer(..detail omitted..).when(service).methodB(Mockito.anyList());
    }

    //testing directly calling mocked method that returns mocked data
    @Test
    public void testMockedMethod() throws Exception {
        List<String> list = //setup details ignored
        List<String> results = service.methodB(list);
        // follow up asserts work
    }

    //testing indirectly calling mocked method that call actual method code
    @Test
    public void testMethodA() throws Exception {
        List<String> list = //setup details ignored
        // NullPointer in methodB since mocking is ignore
        List<String> results = service.methodA(list);
        // assertions never tested since NPE was thrown
    }
}

Does anyone know why when I directly call the mocked method, it returns the doAnswer; but when I indirectly call from within the mocked/spied object it ignores the fact that the method is mocked and calls the original method?

Upvotes: 0

Views: 814

Answers (1)

Ken Chan
Ken Chan

Reputation: 90557

It should work. It seems to me that the NPE exception is because there are some bugs in your codes which already happen before it really executes the stubbed method . What is the stacktrack that you get ?

On the other hand, you can also add some println just before and after calling the stubbed method to verify the codes is really can execute up to that point :

 public List<String> methodA(List<String> list) {
    .......
    System.out.println("before methodB");
    innerList = methodB(list);
    System.out.println("after methodB which return " + innerList);
    ....
}

Upvotes: 0

Related Questions