2014-07-09 8 views

Antwort

10

Sie können den Port mit diesem Code finden:

int port = context.embeddedServletContainer.port 

Welche für die Interessenten in der Java-Äquivalent:

int port = ((TomcatEmbeddedServletContainer)((AnnotationConfigEmbeddedWebApplicationContext)context).getEmbeddedServletContainer()).getPort(); 

Hier ist eine abstrakte Klasse, die Sie erstreckt können, die bis Wraps Diese Initialisierung der Spring-Boot-Anwendung und bestimmt den 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); 
    } 
} 

, die Sie mögen diese verwenden:

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

Die Injektion wird mit Spock arbeiten, so lange wie Sie Ihre spec Klasse konfiguriert haben richtig und haben spock-spring auf dem Classpath. Es gibt eine limitation in Spock Spring, was bedeutet, dass es Ihre Boot-Anwendung nicht bootstrappt, wenn Sie @SpringApplicationConfiguration verwenden. Sie müssen @ContextConfiguration verwenden und stattdessen manuell konfigurieren. Details siehe this answer.

Der zweite Teil des Problems ist, dass Sie einen GString für die @Value nicht verwenden können. Sie könnten die $ zu entkommen, aber es ist einfacher, einfache Anführungszeichen zu verwenden:

@Value('${local.server.port}') 
private int port; 

Putting dies zusammen, erhalten Sie eine spec, die etwa wie folgt aussieht:

@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' 
    } 
} 

Auch die Verwendung von @IntegrationTest("server.port=0") beachten anfordern ein zufälliger Port wird verwendet. Es ist eine gute Alternative zur Konfiguration in application.properties.

+0

@SpringApplicationConfiguration scheint 1.0 mit Spock zu arbeiten. – gilad

+0

Andys Antwort sollte als die echte Antwort markiert sein. Seine Lösung, Port # mit der @Value-Zeichenfolge zu erhalten, ist viel eleganter. – Jacomoman

+0

BTW, @ andy-wilkinson, spock-spring unterstützt jetzt '@ SpringBootTest' als eine einzige Anmerkung, anstatt' @ ContextConfiguration', '@ WebAppConfiguration' und' @ IntegrationTests' zu kombinieren. Alles, was Sie tun müssen, ist: '@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)' – Jacomoman

0

Man könnte dies auch tun:

@Autowired 
private org.springframework.core.env.Environment springEnv; 
... 
springEnv.getProperty("server.port");