有关在Spring Boot应用程序中执行单元测试的说明

时间:2019-02-07 18:11:24

标签: unit-testing spring-boot junit

我摆脱了使用JUnit编写基本单元测试的简单方法,该方法将两个数字相加。我可以使用assert *系列函数调用来验证结果。现在,我要对Spring Boot控制器进行单元测试。

这是单元测试类的示例-

public class MyJunitTest {
    private MockMvc mockMvc;
@Mock
private MyService service;

@InjectMocks
private MyController controller;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void unitTestGetAssessmentDetails() {
    when(service.getTest(Someobject.class)).thenReturn(customObjectWithValues);
    Results results = controller.getCall(someRequestObject);
    assertEquals(results, someOtherObjectPrefilledWithValues);
}
}

我的问题是,如果我知道customObjectWithValues中设置的值,那么someOtherObjectPrefilledWithValues也由我设置,那么assertEquals将始终通过测试,对吗?本质上是在测试是否1 == 1种测试。那么进行这些单元测试的重点是什么?我知道该服务对象不应该连接到实际的数据库,因此我们在嘲笑它。那么进行这些测试有什么意义呢?在这里,我是否想了解如何查看单元测试的大图?

P.S。 -如果违反此论坛的规则,请随时删除此问题。

3 个答案:

答案 0 :(得分:1)

您的测试验证getCall返回了预期结果; 这是黑匣子测试。 由于您正在编写单元测试, 这仅足以“假装”执行单元测试。 这种技术在将代码质量与 单元测试代码覆盖率。

一种更好的技术是确定控制器类将要执行的步骤,并验证每个步骤是否已执行(也许也以正确的顺序执行)。

我将假设MyController.getCall看起来像这样:

@Autowired
private MyService myService;

public BlammyReturnValueType getCall(final BlammyRequestType request)
{
    final BlammyReturnValueType returnValue;

    returnValue = myService.someServiceMethod(request);

    return returnValue;
}

在这种情况下, 我将以下内容添加到unitTestGetAssessmentDetails测试方法中:

... The current stuff including the assert.

Mockito.verify(service, times(1)).someServiceMethod(customObjectWithValues);

这将确认一次调用了服务方法, 在此示例中是正确的。

答案 1 :(得分:1)

好的,单元测试更多地是关于测试写在函数/控制器/服务中的逻辑。现在,您的功能可能非常简单,也可能非常复杂。例如,您的函数可能正在接受UserId并请求,连接到数据库,获取数据并返回数据,并且由于您正在模拟数据库连接,因此您可能会觉得如果将模拟对象作为数据库响应传递,显然得到相同的响应,那么测试的重点是什么。在这种情况下完全不进行测试似乎是正确的。但是,让我再举一个例子,假设您有一个非常复杂的函数,该函数需要一些UserId,获取银行历史记录的用户的全年数据,对其进行累加并计算今年的用户收入。现在,考虑一下此功能有多复杂。现在,由于模拟了数据库连接,您将传递一些数据,因此内部进行了大量计算,并为用户提供了一定的储蓄利息。现在,对于给定的模拟数据,您知道答案应该为X数量。现在,随着时间的流逝,有人犯了一个错误(也许减去了需要添加的内容)。现在,当您运行测试时。该测试将失败,并且您知道逻辑上有问题。并不是在这里,您不是直接期望输出等于模拟数据,而是对数据进行了一些计算,因此在每次更改后验证功能逻辑是否正确,您需要编写一个单元测试来对其进行验证。现在,如果您在此处看到,您的测试不是1 == 1,而是有所不同。这就是为什么人们编写单元测试,以在代码单元中检查其逻辑的原因。

希望这会有所帮助。

答案 2 :(得分:0)

通常,我们分为3层,分别是控制器,服务,存储库(如果愿意,则为DAO)。我通常不测试控制器,因为我没有在其中添加任何逻辑,我只是​​定义端点并调用服务。该服务是我进行大量单元测试的工具,因此您可以将模拟注入到您的服务中。然后,您将模拟您的存储库,以便它不会尝试连接到数据库。

@InjectMocks
private MyService service;

@Mock
private MyRepository myrepo

@Test
public void unitTestGetAssessmentDetails() {
    when(myrepo.find(someInt)).thenReturn(customObjectWithValues);
    Results results = service.serviceMethod(someRequestObject);
    assertEquals(results, someOtherObjectPrefilledWithValues);
}

由于控制器应该没有逻辑,所以它们不需要进行单元测试,因为您正确地说这是1 == 1的测试。但是它们将通过集成测试进行测试