我最近几天一直在玩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)
我尝试了各种各样的东西,但由于加载内容的顺序,没有一个能够正常工作:
所以基本上,我需要我的测试来启动Tomcat,可能会在其中部署我的空心web服务,给我随机端口以便我可以在上下文中添加它,然后然后加载我的TestSpecificConfiguration / CustomerBatchConfiguration。
知道这是否可行?或者WebIntegrationTest注释是否真正针对测试webapps,我们在测试中自己执行http请求?
由于
文森特
=====编辑
在我提交的最新版本的代码中,我使用反射来设置已在Spring上下文中加载的组件上的动态端口。 https://github.com/vincent-fuchs/spring-projects/commit/df7bf3a76fc6109fdacac21d7dd10b045ccd0458
它有效,但显然它不是最好的解决方案。因此,如果一个人有一个干净的方式,这将是伟大的!