Set property with wiremock random port in spring boot test
Consider using Spring Cloud Contract Wiremock
There is already a JUnit Rule builder which allows to specify ${wiremock.port}
to set random port in property/yaml files
Or you can use WireMockRestServiceServer
to bind WireMock to your RestTemplate
so you don't even need to override URLs in your tests.
Use property substitution in your application.properties:
external.baseUrl=http://exampleUrl:${wiremock.server.port}
This requires the wiremock.server.port
property to be set before the SpringBootTest is initialised, which can be achieved by adding the @AutoConfigureWireMock
annotation to your test class.
The property name mentioned in https://stackoverflow.com/a/48859553/309683 (i.e. wiremock.port
) is not correct, at least since Spring Cloud Contract version 2.1.2.RELEASE
.
1. Working example
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class PortServiceTest {
@Autowired
private Environment environment;
@Test
public void shouldPopulateEnvironmentWithWiremockPort() {
assertThat(environment.containsProperty("wiremock.server.port")).isTrue();
assertThat(environment.getProperty("wiremock.server.port")).matches("\\d+");
}
}
2. Other WireMock properties
Other than wiremock.server.port
, @AutoConfigureWireMock
populates the environment with some other properties too:
wiremock.server.https-port
wiremock.server.stubs[]
wiremock.server.files[]
3. Gradle dependencies
To use Spring Cloud Contract WireMock in a Gradle based project, add the following dependency to your project:
testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock:${version}'
4. Using in application.yaml
files
If you configure your test application.yaml
file like this:
sample:
port: ${wiremock.server.port}
And define the following beans:
@Component
@ConfigurationProperties(prefix = "sample")
@Data
public class PortProperties {
private Integer port;
}
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PortService {
private final PortProperties config;
public Integer getPort() {
return config.getPort();
}
}
You can verify that sample.port
is set to the randomly chosen wiremock port:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class PortServiceTest {
@Autowired
private Environment environment;
@Autowired
private PortService portService;
@Test
public void shouldReturnWireMockPort() {
assertThat(portService.getPort())
.isNotNull()
.isEqualTo(Integer.parseInt(environment.getProperty("wiremock.server.port")));
}
}