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

后端 未结 3 1074
广开言路
广开言路 2020-12-29 14:28

Given this entry in application.properties:

server.port=0

which causes Spring Boot to chose a random available port, and testi

相关标签:
3条回答
  • 2020-12-29 14:42

    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.

    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('${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.

    0 讨论(0)
  • 2020-12-29 14:54

    You could do this too:

    @Autowired
    private org.springframework.core.env.Environment springEnv;
    ...
    springEnv.getProperty("server.port");
    
    0 讨论(0)
  • 2020-12-29 14:56

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题