测试你的代码不是微不足道的,尽管并不是不可能.我的第一个想法是使用
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 captor = ArgumentCaptor.forClass(Message.class);
verify(messageDAO, times(2)).makePersistent(captor.capture());
final List 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方法被调用,每次调用messageService.acceptFromOffice(message).在内部,您可以执行所需的所有验证.
注意:谨慎使用,维持此类测试至少可以说是麻烦的.