Home > database >  mockito, how to mock call by reference method on same class
mockito, how to mock call by reference method on same class

Time:08-03

Why i can not mock callReffMethod method (call method by refference) on below code ? the problem is real method of callReffMethod always being called.

public class ManageUserService {

public void callReffMethod(List<String> lsStr, boolean flag){
    if (flag){
        lsStr.add("one");
        lsStr.add("two");
    }

}

public void methodA(){
    List<String> lsStr = new ArrayList<>();
    lsStr.add("zero");
    this.callReffMethod(lsStr, true);
    for(String str : lsStr){
        System.out.println(str);
    }
}

}

//Unit Test:

public class ManageUserServiceTest {

@InjectMocks
private ManageUserService manageUserService;

private AutoCloseable closeable;

@BeforeEach
public void init() {
    closeable = MockitoAnnotations.openMocks(this);
}

@AfterEach
void closeService() throws Exception {
    closeable.close();
}

@Test
void methodATest(){
    List<String> lsData = new ArrayList<>();
    lsData.add("start");
    ManageUserService manageUserServiceA = new ManageUserService();
    ManageUserService userSpy = spy(manageUserServiceA);
    doNothing().when(userSpy).callReffMethod(lsData, true);
    userSpy.methodA();
    verify(userSpy).callReffMethod(ArgumentMatchers.any(ArrayList.class), ArgumentMatchers.any(Boolean.class));
}

}

//The result : zero one two

CodePudding user response:

The problem is the difference between the list you're creating in the test method, which is used to match the expected parameters when "doing nothing":

List<String> lsData = new ArrayList<>();
lsData.add("start");
...
doNothing().when(userSpy).callReffMethod(lsData, true);

and the list created in the tested method, passed to the spy object:

List<String> lsStr = new ArrayList<>();
lsStr.add("zero");
this.callReffMethod(lsStr, true);

You're telling Mockito to doNothing if the list is: ["start"], but such list is never passed to the callReffMethod. ["zero"] is passed there, which does not match the expected params, so actual method is called.

Mockito uses equals to compare the actual argument with an expected parameter value - see: the documentation. To work around that ArgumentMatchers can be used.

You can either fix the value added to the list in the test or match the expected parameter in a less strict way (e.g. using anyList() matcher).

CodePudding user response:

ok i did it by using : where manageUserServiceOne is spy of ManageUserService class

 void methodATest(){
        List<String> lsData = new ArrayList<>();
        lsData.add("start");
        doAnswer((invocation) -> {
            System.out.println(invocation.getArgument(0).toString());
            List<String> lsModify = invocation.getArgument(0);
            lsModify.add("mockA");
            lsModify.add("mockB");
            return null;
        }).when(manageUserServiceOne).callReffMethod(anyList(), anyBoolean());
        manageUserServiceOne.methodA();
        verify(manageUserServiceOne).callReffMethod(ArgumentMatchers.any(ArrayList.class), ArgumentMatchers.any(Boolean.class));
    }
  • Related