使用属性 server.port=0 运行 spock 测试时如何找到 Spring Boot 容器的端口
Posted
技术标签:
【中文标题】使用属性 server.port=0 运行 spock 测试时如何找到 Spring Boot 容器的端口【英文标题】:How to find port of Spring Boot container when running a spock test using property server.port=0 【发布时间】:2014-08-29 21:02:51 【问题描述】:鉴于application.properties
中的此条目:
server.port=0
这会导致 Spring Boot 选择一个随机可用端口,并使用 spock 测试 Spring Boot Web 应用程序,spock 代码如何知道要访问哪个端口?
像这样正常注入:
@Value("$local.server.port")
int port;
不适用于 spock。
【问题讨论】:
【参考方案1】:您可以使用以下代码找到端口:
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;
【讨论】:
【参考方案2】:只要您正确配置了规范类并在类路径中有spock-spring
,注入将与 Spock 一起使用。有一个limitation in Spock Spring,这意味着如果您使用@SpringApplicationConfiguration
,它将不会引导您的引导应用程序。您需要使用@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
中配置它的一个不错的选择。
【讨论】:
@SpringApplicationConfiguration 似乎正在使用 Spock 1.0。 安迪的答案应该被标记为真正的答案。他使用@Value 字符串获取端口号的解决方案更加优雅。 顺便说一句,@andy-wilkinson,spock-spring 现在支持@SpringBootTest
作为单个注释,而不必组合 @ContextConfiguration
、@WebAppConfiguration
和 @IntegrationTests
。所以你所要做的就是:@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
【参考方案3】:
你也可以这样做:
@Autowired
private org.springframework.core.env.Environment springEnv;
...
springEnv.getProperty("server.port");
【讨论】:
以上是关于使用属性 server.port=0 运行 spock 测试时如何找到 Spring Boot 容器的端口的主要内容,如果未能解决你的问题,请参考以下文章
使用 application.properties 中配置的属性,举例:@Value("${server.port}")