Given this entry in application.properties
:
考虑到application.properties中的这个条目:
server.port=0
which causes Spring Boot to chose a random available port, and testing a spring boot web application using spock, how can the spock code know which port to hit?
导致Spring Boot选择一个随机可用的端口,并使用spock测试Spring Boot web应用程序,spock代码如何知道要访问哪个端口?
Normal injection like this:
正常注入是这样的:
@Value("${local.server.port}")
int port;
doesn't work with spock.
不工作,斯波克。
3 个解决方案
#1
11
You can find the port using this code:
您可以使用以下代码找到端口:
int port = context.embeddedServletContainer.port
Which for those interested in the java equivalent is:
对java对等物感兴趣的人是:
int port = ((TomcatEmbeddedServletContainer)((AnnotationConfigEmbeddedWebApplicationContext)context).getEmbeddedServletContainer()).getPort();
Here's an abstract class that you can extends which wraps up this initialization of the spring boot application and determines the port:
这里有一个抽象类,您可以扩展它来完成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);
}
}
Which you can use like this:
你可以这样使用:
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
8
The injection will work with Spock, as long as you've configured your spec class correctly and have spock-spring
on the classpath. There's a limitation in Spock Spring which means it won't bootstrap your Boot application if you use @SpringApplicationConfiguration
. You need to use @ContextConfiguration
and configure it manually instead. See this answer for the details.
只要您正确地配置了spec类并在类路径中有Spock -spring,该注入将与Spock一起工作。Spock Spring有一个限制,这意味着如果您使用@SpringApplicationConfiguration,它不会引导您的引导应用程序。您需要使用@ContextConfiguration并手动配置它。详细信息请参见此答案。
The second part of the problem is that you can't use a GString for the @Value
. You could escape the $
, but it's easier to use single quotes:
问题的第二部分是您不能对@Value使用GString。你可以转义$,但更容易使用单引号:
@Value('${local.server.port}')
private int port;
Putting this together, you get a spec that looks something like this:
把这些放在一起,你会得到一个类似这样的规范:
@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'
}
}
Also note the use of @IntegrationTest("server.port=0")
to request a random port be used. It's a nice alternative to configuring it in application.properties
.
还要注意使用@IntegrationTest(“server.port=0”)请求使用一个随机端口。这是在application.properties中配置它的一个不错的选择。
#3
0
You could do this too:
你也可以这么做:
@Autowired
private org.springframework.core.env.Environment springEnv;
...
springEnv.getProperty("server.port");
#1
11
You can find the port using this code:
您可以使用以下代码找到端口:
int port = context.embeddedServletContainer.port
Which for those interested in the java equivalent is:
对java对等物感兴趣的人是:
int port = ((TomcatEmbeddedServletContainer)((AnnotationConfigEmbeddedWebApplicationContext)context).getEmbeddedServletContainer()).getPort();
Here's an abstract class that you can extends which wraps up this initialization of the spring boot application and determines the port:
这里有一个抽象类,您可以扩展它来完成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);
}
}
Which you can use like this:
你可以这样使用:
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
8
The injection will work with Spock, as long as you've configured your spec class correctly and have spock-spring
on the classpath. There's a limitation in Spock Spring which means it won't bootstrap your Boot application if you use @SpringApplicationConfiguration
. You need to use @ContextConfiguration
and configure it manually instead. See this answer for the details.
只要您正确地配置了spec类并在类路径中有Spock -spring,该注入将与Spock一起工作。Spock Spring有一个限制,这意味着如果您使用@SpringApplicationConfiguration,它不会引导您的引导应用程序。您需要使用@ContextConfiguration并手动配置它。详细信息请参见此答案。
The second part of the problem is that you can't use a GString for the @Value
. You could escape the $
, but it's easier to use single quotes:
问题的第二部分是您不能对@Value使用GString。你可以转义$,但更容易使用单引号:
@Value('${local.server.port}')
private int port;
Putting this together, you get a spec that looks something like this:
把这些放在一起,你会得到一个类似这样的规范:
@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'
}
}
Also note the use of @IntegrationTest("server.port=0")
to request a random port be used. It's a nice alternative to configuring it in application.properties
.
还要注意使用@IntegrationTest(“server.port=0”)请求使用一个随机端口。这是在application.properties中配置它的一个不错的选择。
#3
0
You could do this too:
你也可以这么做:
@Autowired
private org.springframework.core.env.Environment springEnv;
...
springEnv.getProperty("server.port");