【问题标题】:How to find port of Spring Boot container when running a spock test using property server.port=0使用属性 server.port=0 运行 spock 测试时如何找到 Spring Boot 容器的端口
【发布时间】: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。

【问题讨论】:

    标签: testing port spring-boot 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");
      

      【讨论】:

        猜你喜欢
        • 2019-01-27
        • 1970-01-01
        • 2019-07-03
        • 2021-07-23
        • 2015-10-14
        • 2019-04-22
        • 2014-08-15
        • 1970-01-01
        • 2021-06-19
        相关资源
        最近更新 更多