19

我有一个 Spring Boot 应用程序,它启动并执行一个类,该类侦听Application Ready 事件以调用外部服务以获取一些数据,然后使用该数据将一些规则推送到类路径以执行。对于本地测试,我们在应用程序中模拟了外部服务,该服务在应用程序启动期间运行良好。

问题是在测试应用程序时使用spring boot 测试注释和嵌入式码头容器运行它:

  • 随机端口
  • 定义端口

RANDOM PORT的情况下,在应用程序启动时,它会从定义端口的属性文件中获取模拟服务的 url,并且不知道嵌入式容器在哪里运行,因为它是随机获取的,因此无法给出响应.

DEFINED PORT的情况下,对于第一个测试用例文件,它成功运行,但是在拾取下一个文件的那一刻,它会失败,说端口已经在使用中。

测试用例在逻辑上划分为多个文件,需要在容器开始加载规则之前调用外部服务。

在使用定义的端口的情况下,我如何在测试文件之间共享嵌入式容器,或者重构我的应用程序代码,而不是在测试用例执行期间启动时获取随机端口。

任何帮助,将不胜感激。

应用程序启动代码:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Autowired
private SomeService someService;

@Override
public void onApplicationEvent(ApplicationReadyEvent arg0) {

    try {
        someService.callExternalServiceAndLoadData();
    }
    catch (Execption e) {}
    }
 }

测试代码注释:Test1

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test1 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}

测试代码注释:Test2

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test2 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}
4

3 回答 3

23

如果你坚持在多个测试中使用相同的端口,你可以通过注释你的测试类来防止 spring 缓存上下文以进行进一步的测试:@DirtiesContext

在你的情况下:

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")

这是安迪·威尔金森(Andy Wilkinson)对此讨论的回答中的引述

这是按设计工作的。默认情况下,Spring Framework 的测试框架将缓存上下文以供多个测试类重用。您有两个具有不同配置的测试(由于@TestPropertySource),因此它们将使用不同的应用程序上下文。第一个测试的上下文将被缓存并在第二个测试运行时保持打开状态。两个测试都配置为对 Tomcat 的连接器使用相同的端口。因此,在运行第二个测试时,由于与第一个测试中的连接器发生端口冲突,上下文无法启动。你有几个选择:

  1. 使用 RANDOM_PORT
  2. 从 Test2 中删除 @TestPropertySource 以便上下文具有相同的配置,并且可以将第一个测试的上下文重用于第二个测试。
  3. 使用 @DirtiesContext 以便不缓存上下文
于 2018-05-18T13:20:23.980 回答
9

我遇到了同样的问题。我知道这个问题有点老了,但这可能会有所帮助:

使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 的测试也可以使用 @LocalServerPort 注解将实际端口注入到字段中,如下例所示:

来源:https ://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-user-a-random-unassigned-http-port

给出的代码示例是:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    ServletWebServerApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}
于 2018-02-07T04:51:22.300 回答
0

在 application.properties

服务器端口=0

将在随机端口中运行应用程序

于 2020-07-03T04:11:25.370 回答