Unable to set runtime Local Server Port in Spring Boot Test 1.5

19,206

Solution 1

Maybe you forgot to configure the random port for your test web environment.

This should do the trick: @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

Here a test just executed successfully with Spring Boot 1.5.2:

import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortTests {

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

    @Test
    public void getPort() {
        assertThat("Should get a random port greater than zero!", localPort, greaterThan(0));
    }

}

Solution 2

I had the same issue with an application using spring boot 1.4 and found that the event of EmbeddedServletContainerInitializedEvent is a bit delayed - which means it gets triggered after my bean is initialized -, so in order to resolve this i needed to use lazy annotation on the bean that needs to use the port as for example a RestClient bean and it worked. Example:

@Bean
@Lazy(true)
public RESTClient restClient() {
   return new RESTClient(URL + port)
}

Solution 3

You forgot to put @RunWith(SpringRunner.class) above your class decoration.

So, try this.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfig.class, webEnvironment =WebEnvironment.DEFINED_PORT)
public class RestServiceTest {
     @LocalServerPort
     int randomServerPort;
     ...
}

Solution 4

I had the same issue. Adding this dependency solved the problem:

<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-spring -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-spring</artifactId>
    <version>6.2.2</version>
</dependency>
Share:
19,206
Meena Chaudhary
Author by

Meena Chaudhary

Updated on June 05, 2022

Comments

  • Meena Chaudhary
    Meena Chaudhary almost 2 years

    I am using Spring Boot 1.5 for my application. In integration testing I want to fetch the runtime port number of the web server(note: TestRestTemplate is not useful in my case.). There are a few approaches I have tried but none of them seem to work. Below are my approaches.

    First Approach

    @SpringBootTest(classes = TestConfig.class, webEnvironment =WebEnvironment.DEFINED_PORT)
    public class RestServiceTest {
    
    @LocalServerPort      
    protected int port;
    

    In my src/main/resources/config/application.properties file I have defined server port as

    server.port = 8081

    But With this code I am getting error

    Could not resolve placeholder 'local.server.port' in value "${local.server.port}"

    Second Approach

    I have changed

    webEnvironment =WebEnvironment.DEFINED_PORT

    to

    webEnvironment =WebEnvironment.RANDOM_PORT

    and in my src/main/resources/config/application.properties file I have defined

    server.port = 0

    This throws the same as error as the first approach.

    Third Approach

    In third approach I have tried to use

    protected int port;
    
    @Autowired
    Environment environment
    
    this.port = this.environment.getProperty("local.server.port");
    

    this returns null value

    Fourth Approach

    Lastly I have tried to use ApplicationEvents to find out the port number by creating an event listener to listen to EmbeddedServletContainerIntialize

    @EventListener(EmbeddedServletContainerInitializedEvent.class)
    public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {
    this.port = event.getEmbeddedServletContainer().getPort();
    }
    
    public int getPort() {
    return this.port;
    } 
    

    Added the same to TestConfig

    Now, In my test class I have tried use this listener to get the port

    @SpringBootTest(classes = TestConfig.class, webEnvironment =WebEnvironment.RANDOM_PORT)
    public class RestServiceTest {
    
    protected int port;
    
    @Autowired
    EmbeddedServletContainerIntializedEventListener embeddedServletcontainerPort;
    
    this.port = this.embeddedServletcontainerPort.getPort();
    

    this returns 0. Also, I have found out listener event is never triggered.

    It is very straight forward as in the docs and other posts but somehow It is not working for me. Help is much appreciated.

    • M. Deinum
      M. Deinum about 7 years
      Is TestCOnfig your actual application class? As that is what should be loaded (as that contains the @SpringBootAPplication annotation and triggers all things).
    • Meena Chaudhary
      Meena Chaudhary about 7 years
      @M.Deinum TestConfig is a @Configuration file specific to test environment where other beans are defined.
    • M. Deinum
      M. Deinum about 7 years
      Then it won't work.. It requires a full application configuration else the application won't start nor auto-configure and hence no ports will be set.
    • Meena Chaudhary
      Meena Chaudhary about 7 years
      @M.Deinum The same configuration was working in 1.3.8. Also I have tried getting the port in a dummy application without declaring the main class and it works and returns the port.
    • M. Deinum
      M. Deinum about 7 years
      Things change between major versions. It might even depend on the package (and if things are detected). I would suggest trying to define both the application class and test config in the annotation.
    • 8bitjunkie
      8bitjunkie almost 4 years
      1st approach....2nd approach...3rd approach... 4th approach. And therein is the problem. Spring is a mess. I feel your pain and am currently going through the exact same fight, hence finding your question.
  • 8bitjunkie
    8bitjunkie almost 4 years
    Please could you expand your answer to show the dependencies which you have imported (presumably using Maven?). I have the same code as you but it doesn't work for me. There must be some config which I am missing.
  • Christoffer Hammarström
    Christoffer Hammarström almost 3 years
    This was the solution for me.
  • Atorian
    Atorian almost 3 years
    This solved the same error with a usage of @LocalServerPort in a @Component injected into a @RestController. Minor note: @Lazy(true) can simply be @Lazy.
  • Krzysztof Tomaszewski
    Krzysztof Tomaszewski almost 2 years
    This seems to be completely not related to the root issue. This is not a part of Spring Framework or Spring Boot.