我试图模仿以下方法:
public void add(Question question) {
String username = authenticationManager.getUsername();
Candidate candidate = userService.getByUsername(username);
if (!authenticationManager.hasPermission("ROLE_ADMIN")) {
question.setStatus(QuestionStatus.WAITING);
}
question.setCandidate(candidate);
questionRepository.add(question);
}
这是我的尝试:
@Test
public void add_savesQuestionWithStatusWaiting_whenSubmittedAsUser() {
Candidate candidate = new Candidate();
Question question = mock(Question.class);
when(authenticationManager.getUsername()).thenReturn("andreas");
when(userService.getByUsername("andreas")).thenReturn(candidate);
when(authenticationManager.hasPermission("ROLE_ADMIN")).thenReturn(true);
questionService.add(question);
verify(question, times(0)).setStatus(any(QuestionStatus.class));
}
我要做的是测试应用程序逻辑。当用户没有ROLE_ADMIN时,问题状态将设置为等待。我在嘲笑吗?
答案 0 :(得分:0)
在单元测试中,您模拟每个不属于测试单元的依赖项。 在您的情况下,您的单位是questionRepository,您正在尝试测试对象上是否发生了所有预期的交互,但是不是在真实对象上,而是在它们的模拟版本上。这是非常精细和自然的方法。
因此,就你如何使用mockito来说,你做得非常好。什么是不好的是,questionService.add做得太多了。 'add'表示它会将一些对象放入容器而不是其他任何东西。相反,它也在进行复杂的问题对象设置。换句话说,它有副作用。结果是您必须测试的不同边界条件的数量很大。这将使您的测试在将来难以维护。看看你有多少嘲讽。
如果你在一段时间后回到测试中,你会试着弄清楚它在做什么,这会很简单吗? 我还认为测试名称并不反映实际测试的内容。对我来说,'add_savesQuestionWithStatusWaiting_whenSubmittedAsUser'暗示我应该期望最后一个问题应该保存,状态设置为'waiting',而不是使用verify来检查是否没有调用setStatus()。
我会尝试重构add方法代码,所以它只是将元素插入到queryService中。然后我将测试questionService的不同边界条件(例如,当提供null时它将如何表现)。我还会将问题的设置移到应用程序的不同层,并在不同的单元中进行测试。