苦苦挣扎于单元测试和嘲弄

问题描述 投票:1回答:1

我试图嘲笑以下方法:

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时,问题状态将设置为等待。我在嘲笑吗?

java unit-testing mocking
1个回答
0
投票

在单元测试中,您可以模拟不属于测试单元的每个依赖项。在您的情况下,您的单位是questionRepository,您正在尝试测试对象上是否发生了所有预期的交互,但是不是在真实对象上,而是在它们的模拟版本上。这是非常精细和自然的方法。

所以就你如何使用mockito来说,你做得非常好。什么是不好的是,questionService.add做得太多了。 'add'表示它会将一些对象放入容器而不是其他任何东西。相反,它也在进行复杂的问题对象设置。换句话说,它有副作用。结果是您必须测试的不同边界条件的数量很大。这将使您的测试在将来难以维护。看看你必须创造多少嘲讽。

如果你在一段时间后回到测试中,你会试着弄清楚它在做什么,这会很简单吗?我还认为测试名称并不反映实际测试的内容。对我来说,'add_savesQuestionWithStatusWaiting_whenSubmittedAsUser'意味着我应该期望最后一个问题应该保存,状态设置为'waiting',而不是使用verify来检查是否没有调用setStatus()。

我会尝试重构add方法代码,所以它只是将元素插入到queryService中。然后我将测试questionService的不同边界条件(例如,当提供null时它将如何表现)。我还会将问题的设置移到应用程序的不同层,并在不同的单元中进行测试。

© www.soinside.com 2019 - 2024. All rights reserved.