2014-07-09 8 views

risposta

10

È possibile trovare la porta utilizzando questo codice:

int port = context.embeddedServletContainer.port 

Che per chi è interessato al java equivalente è:

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

Ecco una classe astratta che si può estende che avvolge questa inizializzazione dell'applicazione di avvio di primavera e determina la porta:

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

che è possibile utilizzare in questo modo:

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

L'iniezione lavorerà con Spock, a patto che sia stato configurato correttamente la classe spec e hanno spock-spring nel classpath. C'è un limitation in Spock Spring che significa che non avvierà l'avvio dell'applicazione Boot se usi @SpringApplicationConfiguration. È necessario utilizzare @ContextConfiguration e configurarlo manualmente. Vedi this answer per i dettagli.

La seconda parte del problema è che non è possibile utilizzare un GString per @Value. Si potrebbe sfuggire al $, ma è più facile da usare le virgolette singole:

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

aver realizzato tutto questo, si ottiene una specifica che sembra qualcosa di simile:

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

noti anche l'uso di @IntegrationTest("server.port=0") richiedere utilizzare una porta casuale. È una bella alternativa alla sua configurazione in application.properties.

+0

@SpringApplicationConfiguration sembra funzionare utilizzando Spock 1.0. – gilad

+0

La risposta di Andy avrebbe dovuto essere contrassegnata come la vera risposta. La sua soluzione per ottenere la porta # con la stringa @Value è molto più elegante. – Jacomoman

+0

BTW, @ andy-wilkinson, spock-spring ora supporta '@ SpringBootTest' come una singola annotazione invece di dover combinare' @ ContextConfiguration', '@ WebAppConfiguration' e' @ IntegrationTests'. Quindi tutto ciò che dovete fare è: '@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)' – Jacomoman

0

Si potrebbe fare anche questo:

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