解决Spring启动测试中已使用的端口DEFINED PORT

时间:2017-02-15 12:44:15

标签: java spring-boot integration-testing spring-boot-test

我有一个弹出启动应用程序启动并执行一个类来监听应用程序就绪事件以调用外部服务来获取一些数据,然后使用该数据将一些规则推送到类路径以执行。对于本地测试,我们在应用程序中模拟了外部服务,在应用程序启动期间正常运行。

问题是在测试应用程序的同时运行 spring boot test 注释和嵌入式jetty容器:

  • RANDOM PORT
  • DEFINED PORT

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 {.....}

3 个答案:

答案 0 :(得分:3)

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

  

使用@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;

    // ...

}

答案 1 :(得分:1)

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

在你的情况下:

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

以下是Andy Wilkinson对this discussion

的回答
  

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

     
      
  1. 使用RANDOM_PORT
  2.   
  3. 从Test2中删除@TestPropertySource,以便上下文具有相同的配置,并且第一次测试的上下文可以重复用于第二次测试。
  4.   
  5. 使用@DirtiesContext以便不缓存上下文
  6.   

答案 2 :(得分:0)

在application.properties中

server.port = 0

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