简体   繁体   中英

mockito Call real methods

I have this test: but the method checkIfHold is also mocked

@RunWith(MockitoJUnitRunner.class)
public class FrontSecurityServiceTest {

    @Mock
    private FrontSecurityService frontSecurityService
            = mock( FrontSecurityService.class, withSettings().defaultAnswer(CALLS_REAL_METHODS));

    @Test
    public void test1() {
        when(frontSecurityService.getLoggedInUserId()).thenReturn("000");
        frontSecurityService.checkIfHold(9L);
    }
}

I also tried with

   @Mock
    PerService perService;
    @Spy
    private FrontSecurityService frontSecurityService = new FrontOfficeSecurityService(perService);

but then is not mocking the method getLoggedInUserId() , getLoggedInUserId is public, non-static, and non-final.

I also tried, there it works, but MenService is called inside checkIfHold is null

@RunWith(SpringJUnit4ClassRunner.class)
public class FrontSecurityServiceTest {

    @Mock
    MenService menService;
    @Mock
    FrontSecurityService frontSecurityService;
    @Rule
    public MockitoRule rule = MockitoJUnit.rule();


    @Test
    public void test1() {

        MenReturn menReturn1 = MenReturn.builder().build();
        when(menService.getMen(anyString(), anyLong())).thenReturn(Arrays.asList(menReturn1));
         when(frontSecurityService.checkIfHold(anyLong())).thenCallRealMethod();
when(frontSecurityService.getLoggedInUserId()).thenReturn("000");
        frontSecurityService.checkIfHold(9L);
    }

}

I guess that @Spy is what you are looking for. Still, testing FrontSecurityService and also mock it at the same time seems odd to me. Try the following:

@RunWith(MockitoJUnitRunner.class)
public class FrontSecurityServiceTest {

    @Spy
    private FrontSecurityService frontSecurityService;

    @Test
    public void test1() {
        when(frontSecurityService.getLoggedInUserId()).thenReturn("000");
        frontSecurityService.checkIfHold(9L);
    }
}

Ideally, for FrontSecurityServiceTest, you should not be mocking FrontSecurityService. That's your system-under-test, and you don't want to test your mock, you want to test the system you're testing.

As in my other answer on Difference between Mockito @Spy and @Mock(answer = Answers.CALLS_REAL_METHODS) , if you've mocked with CALLS_REAL_METHODS , then you're going to interact with your system (FrontSecurityService) where it has not run any constructors and has not initialized any fields. It is extremely unlikely that FrontSecurityService will work as expected like that.

As with João Dias's answer , @Spy is what you're looking for. As in the docs, you don't need to call the constructor explicitly, but only because @Spy is documented to do so for you . If you don't have a zero-arg constructor, @Spy will require you to call your constructor, so calling the constructor is not a bad habit to get into—especially if you're using a dependency injection framework or some other context where the constructor might gain parameters later. Your IDE doesn't understand Mockito and will not detect that the constructor is being called reflectively.

Once you have a @Spy , things should work as you expect—provided that getLoggedInUserId is public , non- static , and non- final .

The first issue I think is that you are using the @Mock annotation and also using Mockito.mock(...) at the same time. You can mock an object, then tell Mockito which methods should execute the real implementation

Try the following:

@RunWith(MockitoJUnitRunner.class)
public class FrontSecurityServiceTest {

    private FrontSecurityService frontSecurityService = Mockito.mock(FrontSecurityService.class);

    @Test
    public void test1() {
        when(frontSecurityService.getLoggedInUserId()).thenReturn("000");
        when(frontSecurityService.checkIfHold(Mockito.any())).thenCallRealMethod();
        frontSecurityService.checkIfHold(9L);
    }
}

If checkIfHold method returns void then you have to do something like the following:

Mockito.doCallRealMethod().when(frontSecurityService).checkIfHold(Mockito.any());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM