Spring Boot API 的单元测试

Posted

技术标签:

【中文标题】Spring Boot API 的单元测试【英文标题】:Unit testing for Spring Boot API 【发布时间】:2020-08-08 07:41:18 【问题描述】:

我正在开发 Spring Boot Web API,目前正在编写所需的单元测试。

我想知道:为控制器编写单元测试(JUnit + Mockito)还不够吗?由于控制器是我的应用程序的入口点,并且在服务端实现的所有逻辑都是从公开的 API 调用的,为什么我需要为服务端编写测试?

【问题讨论】:

您应该为您的服务编写 JUnit 测试用例,因为它们可以确保您的服务逻辑按预期工作。此外,如果有人在几年后查看您的代码,并且如果他/她试图将一些代码添加到现有功能中,那么服务测试将失败,他/她将知道他们的更改正在破坏部分业务逻辑。他们将不得不相应地更改测试以确保一切正常。 @nrai 你建议我只为服务层编写单元测试,而不是为控制器编写单元测试? 我建议您应该为应用程序中的控制器和服务编写 JUnit 测试。为控制器编写也是必要的,因为它们就像一个入口点,通过测试确保您的端点正是您在控制器中定义的端点是有意义的。如果你有这些测试,没有人可以篡改/破坏代码。 【参考方案1】:

首先,如果您编写测试以涵盖“所需的测试级别”或“完全进行一些测试”的要求,并且已经完成了生产实施,那么为时已晚。在大多数情况下,首先根据您的要求、合同、用例或任何更优化的方法进行测试。不过,我不知道您的情况以及您要实施的事情,因此请将其视为建议并继续讨论您要询问的关键问题。

您的 JUnit(最好是 5 个)和 Mockito 测试(可能使用 MockMvc)是非常好的单元(类似)测试,可以涵盖 Web 通信问题,例如:HTTP 请求类型、内容类型、编码、输入和输出参数 JSON (反)序列化、错误处理等。最好在模拟服务层的情况下进行测试。多亏了这一点,您无需在数据库中准备数据等即可轻松涵盖大量网络案例。

还必须测试核心逻辑。根据它是什么,以单元方式对其进行测试可能是可行的(最容易编写,可以涵盖很多 - 也包括角落 - 案例)。它可以补充一些集成测试,以验证它在集成(Spring Beans、DB 等)中也能正常工作。

如果需要,您还可以通过控制器通过(真实)HTTP 请求从 Web 调用编写一些 E2E 测试,向数据库/数据存储(如果有)提供服务,但我会将其限制在最重要的场景中使用它在您的 CI/CD 管道中以验证部署是否成功完成。

免责声明。我发现这种方法在多种情况下都很有用,但在某些其他情况下,更改平衡点以更好地应用测试肯定会很好。

【讨论】:

【参考方案2】:

我认为您可能对单元测试和集成测试感到困惑。

如果您使用 Mockito,您可能指的是单元测试,其中测试类的范围应该只是当前类。

应该模拟任何外部方法调用。因此,在您为控制器类编写单元测试的情况下,应该模拟服务调用。

您的测试套件应包含

Junit for Controller-- 测试接口契约点,例如 HTTP 方法、请求参数、强制输入、有效请求负载。 Junit 用于所有其他类,包括服务类- 这是为了测试您的应用程序类的核心逻辑 集成测试- 最后是一个集成测试,它可以使用服务类和其他应用程序代码功能来访问您的控制器端点。

【讨论】:

以上是关于Spring Boot API 的单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何为具有 Spring Security 配置的 Spring Boot API 编写单元测试

如何在 Spring Boot REST API 中为 db insert 方法编写模拟单元测试?

Spring boot 配置单元测试

rest-assured : Restful API 测试利器 - 真正的黑盒单元测试(跟Spring-Boot更配哦)

使用注入 java 和 spring boot 的 RestTemplate 类进行单元测试

为控制器类编写负单元测试用例:spring boot