Java 与单元测试和模拟作斗争
我试图模仿以下方法:Java 与单元测试和模拟作斗争,java,unit-testing,mocking,Java,Unit Testing,Mocking,我试图模仿以下方法: public void add(Question question) { String username = authenticationManager.getUsername(); Candidate candidate = userService.getByUsername(username); if (!authenticationManager.hasPermission("ROLE_ADMIN")) {
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));
}
我试图做的是测试应用程序逻辑。当用户没有角色_ADMIN时,问题状态将设置为等待。我做的模拟对吗?在单元测试中,你模拟了不是被测试单元一部分的每个依赖项。 在您的例子中,您的单元是questionRepository,您正在尝试测试对象上的所有预期交互是否都发生,而不是发生在真实对象上,而是发生在它们的模拟版本上。这是一种完美而自然的方法 所以就你如何使用mockito而言,你做得相当不错。不好的是questionService.add做得太多了“添加”表示它会将一些对象放入容器中,而不会放入其他对象。相反,它也在进行复杂的问题对象设置。换句话说,它有副作用。结果是,需要测试的不同边界条件的数量很大。这将使您的测试在将来很难维护。看看你要做多少模拟 如果你在一段时间后回到你的测试,你会试图弄清楚它在做什么,这会很简单吗? 我还认为测试名称并没有反映实际测试的内容。对于我来说,“add_savesQuestionWithStatusWaiting_whenSubmittedAsUser”意味着我应该期望在问题结束时保存状态设置为“waiting”,而不是使用verify检查是否没有调用setStatus()
我将尝试重构add方法代码,以便它所做的只是将元素插入queryService。然后,我将测试questionService的不同边界条件(例如,当提供null时,它将如何工作)。我还会将问题的设置移到应用程序的不同层,并在不同单元中进行测试 你的测试结果是什么?@Luke我在寻找一个答案,说这是正确的方法还是错误的方法。我不确定我是否理解正确。测试通过了。你也可以做验证(问题);验证无交互作用(问题);问题服务添加方法是我的服务层中的一个bean。我不明白我是如何将这些逻辑转移到其他地方的?在阅读了几遍答案之后,我已经阅读/编写了更多的代码,我理解了你的意思。