让其他组件知道@WebIntegrationTest随机端口

时间:2015-06-27 13:44:20

标签: spring spring-boot spring-batch spring-annotations

我最近几天一直在玩Spring引导,我非常喜欢@WebIntegrationTest注释,它允许启动Tomcat并自动部署Spring启动应用程序。它提供了在随机端口上启动Tomcat的选项,如果您正在测试webapp,这非常容易。但我的情况略有不同。整个源代码可在此处获取:

https://github.com/vincent-fuchs/spring-projects

使用Spring Batch,我需要解析Excel文件,并将项目写入REST webService。当我事先知道编写者需要使用的URL时,它能很好地工作,并且我能够使用Spring Boot在几秒钟内测试整个流程,方法是加载一个“空心”@RestController,它接收请求并使它们可用对断言进行测试。

(注意:我确信这对很多人来说都非常有用。如果你试图测试一个Spring Integration配置,它也会有用)

这是我要测试的批处理,而不是webService。但是为了测试这批产品的输出,我需要这个“空心”的web服务。

     @RunWith(SpringJUnit4ClassRunner.class)
     @SpringApplicationConfiguration(classes = 
     {
      //the webservice client that the batch should use (planning for SOAP impl later)
      RestCustomerWsClient.class,
      //the "target" web server, with the 'hollow' endpoint listening
      TargetRESTSystem.class,
      //the application under test and its config
      TestSpecificConfiguration.class,
      CustomerBatchConfiguration.class}
                                )
    @WebIntegrationTest("server.port:8080")
    @IntegrationTest({"spring.batch.job.enabled=false"})
    public class CustomerBatchWithRestTest {

    @Value("${local.server.port}") 
    public int targetWebServerPort;


    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Autowired
    private DummyCustomerController endpoint ;

    @Autowired
    private ConfigurableApplicationContext  appCtx ;

    @Autowired
    private ConfigurableEnvironment env;


    @Before
    public void loadDynamicProperty() {

        EnvironmentTestUtils.addEnvironment(appCtx, "target.port:"+targetWebServerPort);

        assertThat(env.getProperty("target.port")).isEqualTo(String.valueOf(targetWebServerPort)).as("port for target server is not register correctly in properties");
    }




    @Test
    public void targetShouldReceiveExpectedCustomer() throws Exception {


        JobExecution jobExecution = jobLauncherTestUtils.launchJob();

        //assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED);
        assertThat(endpoint.getReceivedCustomers()).hasSize(1);

        Customer actualCustomer=endpoint.getReceivedCustomers().get(0);
        assertThat(actualCustomer.getId()).isEqualTo(1);
        assertThat(actualCustomer.getFirstName()).isEqualTo("Vincent");
        assertThat(actualCustomer.getLastName()).isEqualTo("FUCHS");
    }

}

通过这些注释,TargetRESTSystem将部署在端口8080上的tomcat中。

在批处理方面,写入的组件配置如下,使用属性文件给出target.port = 8080:

public class RestCustomerWsClient implements CustomerWsClient {

    @Value("${target.host}")
    private String targetHost="undefined";

    @Value("${target.port}")
    private String targetPort="undefined";

    @Override
    public void sendCustomer(Customer customerFromExcel) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.postForEntity("http://"+targetHost+":"+targetPort+"/integrate", customerFromExcel, null);

        System.out.println("sent client integration request");
    }
}   

就像我说的,这很有效,因为我自己定义了端口,并使WebIntegrationTest注释与批处理侧的属性文件之间的值匹配。

但是,如果我想让我的测试更加健壮并使用随机端口,因为如果8080已被其他进程使用,我不希望它失败怎么办?我可以改用它:

@WebIntegrationTest(randomPort=true)

我尝试了各种各样的东西,但由于加载内容的顺序,没有一个能够正常工作:

  • @Before方法将动态值放在属性中,但我需要刷新上下文后,Spring不允许我
  • 我也尝试过调整ApplicationContextInitializer / AbstractGenericContextLoader,但是当它们被调用时,Tomcat还没有启动,我还没有随机值。

所以基本上,我需要我的测试来启动Tomcat,可能会在其中部署我的空心web服务,给我随机端口以便我可以在上下文中添加它,然后然后加载我的TestSpecificConfiguration / CustomerBatchConfiguration。

知道这是否可行?或者WebIntegrationTest注释是否真正针对测试webapps,我们在测试中自己执行http请求?

由于

文森特

=====编辑

在我提交的最新版本的代码中,我使用反射来设置已在Spring上下文中加载的组件上的动态端口。 https://github.com/vincent-fuchs/spring-projects/commit/df7bf3a76fc6109fdacac21d7dd10b045ccd0458

它有效,但显然它不是最好的解决方案。因此,如果一个人有一个干净的方式,这将是伟大的!

0 个答案:

没有答案