2014-07-09 4 views
7

application.properties में इस प्रविष्टि को देखते हुए:जब एक स्पॉक परीक्षण चल संपत्ति server.port का उपयोग कर स्प्रिंग बूट कंटेनर के बंदरगाह को खोजने के लिए कैसे = 0

server.port=0 

जो वसंत बूट एक यादृच्छिक उपलब्ध पोर्ट चुना है का कारण बनता है, और एक परीक्षण स्पॉक बूट वेब एप्लिकेशन स्पॉक का उपयोग करके, स्पॉक कोड कैसे पता लगा सकता है कि किस पोर्ट को हिट करना है? इस तरह

सामान्य इंजेक्शन:

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

स्पॉक के साथ काम नहीं करता।

उत्तर

10

आपको पोर्ट इस कोड का उपयोग पा सकते हैं:

int port = context.embeddedServletContainer.port 

जो जावा बराबर में रुचि रखने वालों के लिए है:

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

यहाँ एक अमूर्त वर्ग है कि आप का विस्तार कर सकते हैं जो ऊपर लपेटता है

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

इंजेक्शन, जब तक कि आप अपनी कल्पना वर्ग ठीक से कॉन्फ़िगर किया गया है स्पॉक के साथ काम करते हैं और classpath पर spock-spring होगा। limitation in Spock Spring है जिसका अर्थ यह है कि यदि आप @SpringApplicationConfiguration का उपयोग करते हैं तो यह आपके बूट एप्लिकेशन को बूटस्ट्रैप नहीं करेगा। आपको @ContextConfiguration का उपयोग करने और इसके बजाय इसे मैन्युअल रूप से कॉन्फ़िगर करने की आवश्यकता है। विवरण के लिए this answer देखें।

समस्या के दूसरे भाग है कि आप @Value के लिए एक gstring उपयोग नहीं कर सकते है। आप $ बच सकता है, लेकिन यह एकल उद्धरण का उपयोग करना आसान है:

@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") के उपयोग पर ध्यान दें अनुरोध करने के लिए:

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

इस एक साथ रखें, यदि आप एक युक्ति है कि कुछ इस तरह दिखता मिलता है एक यादृच्छिक बंदरगाह इस्तेमाल किया जाना चाहिए। application.properties में इसे कॉन्फ़िगर करने का यह एक अच्छा विकल्प है।

+0

@SpringApplicationConfiguration स्पॉक 1.0 का उपयोग कर काम कर रहा है। – gilad

+0

एंडी का जवाब असली जवाब के रूप में चिह्नित किया जाना चाहिए था। @Value स्ट्रिंग के साथ पोर्ट # प्राप्त करने का उनका समाधान अधिक सुरुचिपूर्ण है। – Jacomoman

+0

Btw, @ Andy-विल्किनसन, स्पोक्स वसंत अब '@ SpringBootTest' बजाय गठबंधन करने के लिए' @ ContextConfiguration', '@ WebAppConfiguration' होने के एक भी टिप्पणी के रूप में समर्थन करता है, और' @ IntegrationTests'। तो आपको बस इतना करना है: '@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) ' – Jacomoman

0

आप ऐसा भी कर सकता है:

@Autowired 
private org.springframework.core.env.Environment springEnv; 
... 
springEnv.getProperty("server.port"); 
संबंधित मुद्दे