0

I am tyring to partially mock a spring bean so that only one of the methods called within another method is mocked by the Spy

@ActiveProfiles(profiles = {Profiles.TEST})
public class ServiceTestMockito {

    @Autowired
    private ServiceBean serviceBean;

    @Autowired
    private DAO dao;

    @Test
    public void testSpy() {

        ServiceBean serviceBeanSpy = Mockito.spy(serviceBean);
        doReturn(true).when(serviceBeanSpy).methodB(Mockito.any());
        Assert.isTrue(serviceBeanSpy.methodA(new Employee()), "This should be true");      
    }
}

public class ServiceBean {

    public Boolean methodB(Employee employee) {
        return false;
    }

    public Boolean methodA(Employee employee){
        return methodB(employee);       
    }

}

I used a debugger to see if serviceBean is an different instance than serverBeanSpy but turns out they are the same. I am not sure what am I missing here

I did refer to the following questions but everyone seems to find the issue with the way mock is declared/called but I am following the format mentioned in the questions/forums below:

Question_1

Mockito_Docs

Question_2

Question_3

So when I run the test, the assert always fails because the spy isn't working and I get an actual false returned from methodB

I even stepped over the debugger to methodB and I see it being executed. I believe methodB should not have been called at all.

Nick Div
  • 5,338
  • 12
  • 65
  • 127
  • It is not clear what isn't working / what is your question. – Yoav Gur Oct 18 '18 at 08:06
  • When I debug, I see the methodB getting called. I thought it would be mocked and would not be called. Plus the assert always fails so that means spy isnt working – Nick Div Oct 18 '18 at 08:19
  • Mockito creates a proxy around your ServiceBean when you create a spy, but when you call methodA, which itself isnt spied, it will internally call methodB that is in that case not spied, as it is called from within your instance. – mrkernelpanic Oct 18 '18 at 08:34
  • @NickDiv Interesting. You are right that it should be mocked. Do you also get 'false' instead of 'true'? – Yoav Gur Oct 18 '18 at 08:36
  • @YoavGur Yes the return value is false – Nick Div Oct 19 '18 at 07:34
  • @mrkernelpanic But the methodA is called using the spy and the same spy would be calling methodB right? – Nick Div Oct 19 '18 at 07:36
  • @NickDiv Yes, but methodA is not spied/ mocked so the real implementation will be called... – mrkernelpanic Oct 19 '18 at 07:51
  • @mrkernelpanic Thats fine, but the methodB would also be called on the same spy which is mocked. Shouldn't that return whats configured. This example is similar to questions in the post. Just different class names and method names – Nick Div Oct 19 '18 at 08:03
  • @mrkernelpanic @NickDiv when object `o` is spied, method `methodB()` is "overriden" in the spy, and method `methodA()` is called on the spy, any call from `methodA()` to `methodB()` should invoke the "spied" / "overriden" method. – Yoav Gur Oct 19 '18 at 08:38
  • 1
    I tested this code with the latest Mockito version, with the only change being creating ServiceBean with `new` rather than use `@Autowired`, and it worked as expected (i.e. call to `methodB()` returned `true`). – Yoav Gur Oct 19 '18 at 08:40
  • @YoavGur Ill try that, thanks a lot :) – Nick Div Oct 19 '18 at 09:59

0 Answers0