在单体 SpringBoot 应用程序中创建集成测试

Creating integration tests in a monolithic SpringBoot application

我被要求为一个非常大的 SpringBoot 项目中的服务创建一个集成测试,该项目产生了数十个已实现的服务。当应用程序执行时,所有这些服务都会被部署——我想避免部署与我为其创建测试的服务无关的所有服务。不幸的是,我(还)没有像我希望的那样有足够的 spring 启动测试经验,因此我想知道解决这个问题的最佳方法是什么。

我正在考虑在测试 class 中用 @MockBean 注释对所有不相关的服务进行注释,并在测试 class 中对所有相关的服务进行注释 @Autowire,但我不确定这是否合适路要走。谁能指出我正确的方向?

谢谢。

如果您必须创建 spring 集成测试,您必须: - 通过在测试 class 上使用注释来调用 spring 上下文 - 例如:@RunWith(SpringJUnit4ClassRunner.class) - 在您不打算测试但它们是测试的一部分的服务上使用@MockBean 或@SpyBean 注释 methods/class - 在您要测试的 class 上使用 @Autowired 注释。 要验证结果,您可以使用 Junit4 或 Junit5 断言,为了验证行为,您可以使用 Mockito

答案在很大程度上取决于集成测试的范围。我将尝试涵盖两种主要方式,您可以 google 等待更多示例和详细信息。 Spring Boot testing documentation也是你的朋友

切片

Spring Boot 提供名为 slices. For example there's a slice for testing your controllers - @WebMvcTest 的测试实用程序 - 此测试将加载所有配置,以便从 HTTP 和指定的控制器 (@WebMvcTest(YourController.class)) 调用您的应用程序。之后,您需要决定如何处理该控制器的依赖项。

您可以:

  • @MockBean 来嘲笑他们。
  • @Import提供真正的实现(或附加配置)(然后你必须再次处理新导入的依赖项的依赖项)。
  • 加载 Spring 引导自动配置的附加部分。这可以使用 @AutoConfigureSomething 注释来完成。 - 所有切片基本上都是自动配置注释的组合,您可以自由地将它们添加到您的测试中。例如,查看 annotations on DataJpaTest 以了解如何添加功能以设置 Spring 带有测试数据库的引导数据 JPA。

您的每个测试最多可以有一个切片,但您可以导入任意数量的附加服务、配置、模拟、自动配置等。关键是——您选择为您的测试配置的内容;具有新依赖关系的新不相关服务不应破坏现有测试。

SpringBootTest

另一种方法是 @SpringBootTest 注释——这是相反的方向——默认情况下它会加载所有内容,您可以使用 @MockBean@EnableAutoConfiguration(exclude=SomeClass) 等排除不需要的内容.

添加新服务时当然存在破坏现有测试的危险。 - 这不应该经常发生,因为一切都是自动配置的,但它仍然是可能的,尤其是在具有更多配置的整体中。

我有一个类似的问题,希望能够在 Springboot 中隔离特定组件(或服务)的集成测试;我的限制是我必须使用 JUnit5 和 Mockito。

我从 Baeldung 找到了这两个帖子,它们像往常一样只给出了特定场景的特定答案,而不是通用解决方案: https://www.baeldung.com/injecting-mocks-in-spring https://www.baeldung.com/junit-5-runwith

长话短说我找到了如下解决方案:

  1. 在集成测试的测试文件夹中为您的组件创建如下配置 class(下面的示例是我想要集成测试拦截器组件;我有编辑名称):

  2. 您可以模拟 bean,或者您可以实例化没有依赖关系的 bean(可以说是叶 bean)

  3. 然后在你的集成测试中你可以使用后一个配置。为了让您的组件在测试(剪切)下满足其依赖性。我的拦截器有 3 个依赖级别:

  4. 最后,在您的集成测试中,您可以使用以下方法来模拟您模拟出的 bean 的方法调用: when(cut.getInitRequestRepo().initRequest(ArgumentMatchers.any(InParamInitRequest.class))).thenReturn(outParamInitRequest);

我使用的POM依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>
 <!-- Testing with Mocks -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>3.11.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>3.11.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.10.0</version>
            <scope>test</scope>
        </dependency>