Checking method

public Message findOne(Long id) { Message message = messageRepository.findOne(id); if (message == null) { throw new DataNotFoundException("Data with id=" + id + " not found."); } return message; } 

test option 1, passes even if in the tested method replace DataNotFoundException with NullPointerException. Should not like?

 @Test(expected = DataNotFoundException.class) public void findOneIsNullThenException1() { when(messageServiceImp.findOne(2L)).thenThrow(DataNotFoundException.class); Message testMessage = messageServiceImp.findOne(2L); } 

Test option 2, does not pass either

 @Test(expected = DataNotFoundException.class) public void findOneIsNullThenException() { //prepare when(messageServiceImp.findOne(2L)); then(caughtException()) .isInstanceOf(DataNotFoundException.class) .hasMessageContaining("Data with id=2 not found."); // А так же пробовал с thenThrown(DataNotFoundException.class); } 

getting an error

 java.lang.Exception: Unexpected exception, expected<com.sttech.springrest.exception.DataNotFoundException> but was<java.lang.AssertionError> .... Caused by: java.lang.AssertionError: Expecting actual not to be null .... Eg thenReturn() may be missing. Examples of correct stubbing: when(mock.isOk()).thenReturn(true); when(mock.isOk()).thenThrow(exception); doThrow(exception).when(mock).someVoidMethod(); Hints: 1. missing thenReturn() 2. you are trying to stub a final method, you naughty developer! 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

Addition:

Something I stopped understanding how to test with mockito. I have a class MessageServiceImp in it there are methods that I want to test. I will build on all of the same method as above, but test it not only for exceptions.

In the class MessageServiceImp there is a MessageRepository dependency that needs to be injected, so we mark it as wet and inject it into the class.

 @Mock private MessageRepository messageRepository; @InjectMocks MessageServiceImp messageServiceImp; 

Next, the test itself.

 @Test public void findOne() throws Exception { //prepare when(messageRepository.findOne(ID)).thenReturn(MESSAGE); //testing Message testMessage = messageServiceImp.findOne(ID); //validate verify(messageRepository).findOne(ID); } 

In this form, the test passes, we look, and what does he even test there? it seems like I should call the findOne method and return the MESSAGE object (in fact, I would have approached and returning any anyObject() object). We check, change in the checked method the return value to null and ... the test still passes. I after all expect an object, but I get null and the test passes.

What am I doing wrong?

  • You need a messageRepository, not a messageServiceImp. - Vartlok
  • @Vartlok I tried with the messageRepository and everything became even more confusing. Added above. - Sergei R
  • Have you tried debazhit? Check what is going on inside messageServiceImp.findOne, why null is returned, and not returned. In appearance, you now have all the rules. - Vartlok
  • @Vartlok Yes, everything seems to be normal there, it calls the messageRepository if it receives either an object or if it does not find a null (in this case throws an exception). I do not understand why if instead of return message; I return return null; the test passes, it expects to receive an object and not null. - Sergei R
  • I walked again carefully debager. I understand correctly that my test checks what the messageRepository will return in the when ... thenReturn? If so, then the object returns. But I want to check that MessageServiceImp.findOne () returns, but I’m sort of testing this method. - Sergei R

1 answer 1

 @Test public void findOne() throws Exception { // prepare when(messageRepository.findOne(ID)).thenReturn(MESSAGE); // testing Message testMessage = messageServiceImp.findOne(ID); // validate verify(messageRepository).findOne(ID); assertEquals(MESSAGE, messageServiceImp.findOne(ID)); } 

The when.thenReturn followed by verify construction verifies that the mock call has been triggered, in this case

 Message message = messageRepository.findOne(id); 

And returns an object and nothing else. And an additional check, assertEquals, already checks the return value of the MessageServiceImp.findOne () method itself.