-1

I'm trying to set up a test that will hit a Spring Boot MVC endpoint (http://localhost:$port/api/v1/beer in my case) using Spock and the GOJI HTTP client. I would like to set up the HTTP client once, in setupSpec. Since I'm using @SpringBootTest(webEnvironment = RANDOM_PORT), I need to get the randomly-assigned port in order to provide it to the HTTP client's constructor: beerClient = new HttpClient(baseUrl: "http://localhost:$localPort"). To do this, I have a field localPort annotated with both Spock's @Shared and Spring Boot's @org.springframework.boot.test.web.server.LocalServerPort. Unfortunately, the value of localPort is null. However, if I leave off the @Shared annotations on the HTTP client declaration and on localPort and use setup instead of setupSpec, localPort does have a value. What is causing this difference? Test class is below.

@SpringBootTest(webEnvironment = RANDOM_PORT)
class BeerControllerOpenApiTest extends Specification {
//    @Shared
    @LocalServerPort
    Integer localPort

//    @Shared
    HttpClient beerClient

//    void setupSpec() {
//        beerClient = new HttpClient(baseUrl: "http://localhost:$localPort")
//    }
    void setup() {
        beerClient = new HttpClient(baseUrl: "http://localhost:$localPort")
    }

    def "test list beers"() {
        when:
        def response = beerClient.get(
            path: "/api/v1/beer",
            headers: ["Content-Type": "application/json"]
        )

        then:
        response.statusCode == 200
    }
}
spartanhooah
  • 183
  • 4
  • 15
  • possible duplicate: https://stackoverflow.com/questions/50239369/spring-boot-test-failing-to-autowire-port-with-localserverport-annotation – J Asgarov May 19 '23 at 06:10
  • I tried adding `@ContextConfiguration` as well as making the test implement `ApplicationListener`, but neither approach got the port to have a value in `setupSpec` – spartanhooah May 19 '23 at 12:41

1 Answers1

1

The Spring context is not loaded when setupSpec() is executed, so you can't access anything from it.

If you only want to do it once I'd suggest to move the HttpClient declaration into the Spring context, e.g., by using @TestContext. Alternatively, you can use a @Shared field and a simple if condition.

    @Shared
    HttpClient beerClient

    void setup() {
        if(beerClient == null)
            beerClient = new HttpClient(baseUrl: "http://localhost:$localPort")
        }
    }
Leonard Brünings
  • 12,408
  • 1
  • 46
  • 66