Ответ 1
Тестирование вашего кода не является тривиальным, хотя и не невозможным. Моя первая идея заключалась в том, чтобы использовать ArgumentCaptor, что намного проще использовать и понимать по сравнению с ArgumentMatcher. К сожалению, тест по-прежнему не удается - причины, безусловно, выходят за рамки этого ответа, но я могу помочь, если это вас интересует. Тем не менее, я нахожу этот тестовый пример достаточно интересным, чтобы его можно было показать (не правильное решение):
@RunWith(MockitoJUnitRunner.class)
public class MessageServiceTest {
@Mock
private MessageDAO messageDAO = mock(MessageDAO.class);
private MessageService messageService = new MessageService();
@Before
public void setup() {
messageService.setDao(messageDAO);
}
@Test
public void testAcceptFromOffice() throws Exception {
//given
final Message message = new Message();
//when
messageService.acceptFromOffice(message);
//then
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(messageDAO, times(2)).makePersistent(captor.capture());
final List<Message> params = captor.getAllValues();
assertThat(params).containsExactly(message, message);
assertThat(params.get(0).getStatus()).isEqualTo(0);
assertThat(params.get(1).getStatus()).isEqualTo(1);
}
}
К сожалению, рабочее решение требует довольно сложного использования Answer. Вкратце, вместо того, чтобы позволить Mockito записывать и проверять каждое обращение, вы предоставляете свой метод обратного вызова, который выполняется каждый раз, когда ваш тестовый код выполняет данный макет. В этом методе обратного вызова (MakePersistentCallback
объект в нашем примере) у вас есть доступ к параметрам, и вы можете изменить возвращаемое значение. Это тяжелая пушка, и вы должны использовать ее с осторожностью:
@Test
public void testAcceptFromOffice2() throws Exception {
//given
final Message message = new Message();
doAnswer(new MakePersistentCallback()).when(messageDAO).makePersistent(message);
//when
messageService.acceptFromOffice(message);
//then
verify(messageDAO, times(2)).makePersistent(message);
}
private static class MakePersistentCallback implements Answer {
private int[] expectedStatuses = {0, 1};
private int invocationNo;
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
final Message actual = (Message)invocation.getArguments()[0];
assertThat(actual.getStatus()).isEqualTo(expectedStatuses[invocationNo++]);
return null;
}
}
Пример не завершен, но теперь тест преуспевает и, что более важно, терпит неудачу, когда вы изменяете почти что-либо в CUT. Как вы можете видеть, метод MakePersistentCallback.answer
вызывается каждый раз, когда вызывается mocked messageService.acceptFromOffice(message)
. Внутри naswer
вы можете выполнить все необходимые проверки.
NB: используйте с осторожностью, поддержание таких тестов может быть проблематичным, если не сказать больше.