11. Using the Stubs

The Initializr project publishes WireMock stubs for all the JSON responses that are tested in the project. If you are writing a client for the Initializr service, you can use these stubs to test your own code. You can consume them with the raw Wiremock APIs, or via some features of Spring Cloud Contract.

[Tip]Tip

WireMock is an embedded web server that analyses incoming requests and chooses stub responses based on matching some rules (e.g. a specific header value). So if you send it a request which matches one of its stubs, it will send you a response as if it was a real Initializr service, and you can use that to do full stack integration testing of your client.

11.1 Using WireMock with Spring Boot

11.1.1 Loading Stubs from the Classpath

A convenient way to consume the stubs in your project is to add a test dependency:

<dependency>
    <groupId>io.spring.initializr</groupId>
    <artifactId>initializr-web</artifactId>
    <classifier>stubs</classifier>
    <version>{project-version}</version>
    <scope>test</scope>
</dependency>

and then pull the stubs from the classpath. In a Spring Boot application, using Spring Cloud Contract, you can start a WireMock server and register all the stubs with it like this:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWireMock(port = 0,
    stubs="classpath:META-INF/io.spring.initializr/initializr-web/0.4.0.RELEASE")
public class ClientApplicationTests {

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

    ...

}

The Wiremock features come with Spring Cloud Contract Wiremock:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-wiremock</artifactId>
    <scope>test</scope>
</dependency>
[Tip]Tip

This dependency is managed by the spring-cloud-contract-dependencies BOM.

11.1.2 Using the Stub Runner

Alternatively you can configure the stub runner to look for the artifact, using a different Spring Cloud Contract dependency: spring-cloud-starter-contract-stub-runner. The example below will automatically download, if necessary, the defined version of the initializr stubs (so you don’t need the stubs declared as a dependency):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-stubrunner</artifactId>
    <scope>test</scope>
</dependency>

The test should use @AutoConfigureStubRunner instead:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@AutoConfigureStubRunner(
    ids = "io.spring.initializr:initializr-web:0.4.0.RELEASE",
    repositoryRoot = "https://repo.spring.io/snapshot")
public class ClientApplicationTests {

    @Autowired
    private StubFinder stubFinder;


    ...

}

Here is an example of a test that retrieves the metadata of the service. The assertions do not matter much here but it illustrates how you could integrate that in the test suite of a custom client:

public class ClientApplicationTests {

	@Autowired
	private StubFinder stubFinder;

	@Autowired
	private RestTemplate restTemplate;

	@Test
	public void testCurrentMetadata() throws IOException {
		RequestEntity<Void> request = RequestEntity.get(createUri("/"))
				.accept(MediaType.valueOf("application/vnd.initializr.v2.1+json"))
				.build();

		ResponseEntity<String> response = this.restTemplate
				.exchange(request, String.class);
		assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
		// other assertions here
	}

	private URI createUri(String path) {
		String url = this.stubFinder.findStubUrl("initializr-web").toString();
		return URI.create(url + path);
	}

	@TestConfiguration
	static class Config {

		@Bean
		public RestTemplate restTemplate(RestTemplateBuilder builder) {
			return builder.build();
		}

	}

}

Then you have a server that returns the stub of the JSON metadata (metadataWithCurrentAcceptHeader.json) when you send it a header Accept:application/vnd.initializr.v2.1+json (as recommended).

11.2 Names and Paths of Stubs

The stubs are laid out in a jar file in a form (under "**/mappings") that can be consumed by WireMock just by setting its file source. The names of the individual stubs are the same as the method names of the test cases that generated them in the Initializr project. So for example there is a test case "metadataWithV2AcceptHeader" in MainControllerIntegrationTests that makes assertions about the response when the accept header is application/vnd.initializr.v2.1+json. The response is recorded in the stub, and it will match in WireMock if the same headers and request parameters that were used in the Initializr test case and used in the client. The method name usually summarizes what those values are.

The stub runner, and the @AutoConfigureWireMock in the examples above loads all the stubs into WireMock, so you don’t necessarily need to know the names of the stubs. You can also register stubs one by one, though, in which case it would help to scan the stubs jar and compare the file names with the test methods. For instance, if you look in the stubs jar, you will see a file called metadataWithV2AcceptHeader.json and, in the initializr-web project, a test method called metadataWithV2AcceptHeader which generated it.