How to find port of Spring Boot container when running a spock test using property server.port=0

port, spock, spring-boot, testing

Solution

You can find the port using this code:

int port = context.embeddedServletContainer.port

Which for those interested in the java equivalent is:

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:

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;
    }
}

Problem

Given this entry in `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? Normal injection like this: ``` @Value("${local.server.port}") int port; ``` doesn't work with spock.

Original source

Related problems