假设在application.properties
文件中有以下内容:
server.port=0
本文涉及的问题是如何在使用Spring Boot开发Web应用时选择一个随机可用端口,以及如何在Spock中进行测试。当Spring Boot选择一个随机可用端口时,我们如何让Spock代码知道要访问哪个端口呢?
像这样进行普通注入:
@Value("${local.server.port}")
int port;
不兼容spock。
假设在application.properties
文件中有以下内容:
server.port=0
本文涉及的问题是如何在使用Spring Boot开发Web应用时选择一个随机可用端口,以及如何在Spock中进行测试。当Spring Boot选择一个随机可用端口时,我们如何让Spock代码知道要访问哪个端口呢?
像这样进行普通注入:
@Value("${local.server.port}")
int port;
不兼容spock。
你可以使用这段代码找到端口:
int port = context.embeddedServletContainer.port
对于那些对Java等效性感兴趣的人来说,它是:
int port = ((TomcatEmbeddedServletContainer)((AnnotationConfigEmbeddedWebApplicationContext)context).getEmbeddedServletContainer()).getPort();
这是一个抽象类,你可以继承它来包装Spring Boot应用程序的初始化并确定端口:
abstract class SpringBootSpecification extends Specification {
@Shared
@AutoCleanup
ConfigurableApplicationContext context
int port = context.embeddedServletContainer.port
void launch(Class clazz) {
Future future = Executors.newSingleThreadExecutor().submit(
new Callable() {
@Override
public ConfigurableApplicationContext call() throws Exception {
return (ConfigurableApplicationContext) SpringApplication.run(clazz)
}
})
context = future.get(20, TimeUnit.SECONDS);
}
}
你可以像这样使用:
class MySpecification extends SpringBootSpecification {
void setupSpec() {
launch(MyLauncher.class)
}
String getBody(someParam) {
ResponseEntity entity = new RestTemplate().getForEntity("http://localhost:${port}/somePath/${someParam}", String.class)
return entity.body;
}
}
spock-spring
。 Spock Spring存在限制, 这意味着如果您使用@SpringApplicationConfiguration
,它不会引导您的Boot应用程序。 您需要手动使用@ContextConfiguration
进行配置。有关详细信息,请参见this answer。@Value
使用GString。 您可以转义$
,但使用单引号更容易:@Value('${local.server.port}')
private int port;
@ContextConfiguration(loader = SpringApplicationContextLoader, classes = SampleSpockTestingApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port=0")
class SampleSpockTestingApplicationSpec extends Specification {
@Value("\${local.server.port}")
private int port;
def "The index page has the expected body"() {
when: "the index page is accessed"
def response = new TestRestTemplate().getForEntity(
"http://localhost:$port", String.class);
then: "the response is OK and the body is welcome"
response.statusCode == HttpStatus.OK
response.body == 'welcome'
}
}
@IntegrationTest("server.port=0")
请求使用随机端口。这是一个很好的替代方法,不需要在application.properties
中进行配置。@Autowired
private org.springframework.core.env.Environment springEnv;
...
springEnv.getProperty("server.port");
@SpringBootTest
作为单个注释,而不必组合@ContextConfiguration
,@WebAppConfiguration
和@IntegrationTests
。所以你只需要这样做:@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
- Jacomoman