= Using the Stubs

Spring Initializr project publishes
https://github.com/tomakehurst/wiremock[WireMock] stubs for all the JSON responses
that are tested in the project. If you are writing a client for Spring 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
https://github.com/spring-cloud/spring-cloud-contract[Spring Cloud Contract].

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.



== Using WireMock with Spring Boot
=== Loading Stubs from the Classpath
A convenient way to consume the stubs in your project is to add a test dependency:

[source,xml,indent=0,subs="attributes,specialchars"]
----
	<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, as shown in the following JUnit 5-based example:

[source,java,indent=0,subs="attributes"]
----
	@SpringBootTest
	@AutoConfigureWireMock(port = 0,
		stubs="classpath:META-INF/io.spring.initializr/initializr-web/{spring-initializr-version}")
	class ClientApplicationTests {

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

		...

	}
----

The Wiremock features come with Spring Cloud Contract Wiremock:

[source,xml,indent=0]
----
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-contract-wiremock</artifactId>
		<scope>test</scope>
	</dependency>
----

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



=== 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 Spring Initializr stubs (so you don't need the
stubs declared as a dependency):

[source,xml,indent=0,subs="attributes,specialchars"]
----
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-contract-stubrunner</artifactId>
		<scope>test</scope>
	</dependency>
----

The test should use `@AutoConfigureStubRunner` instead, as shown in the following JUnit
5-based example:

[source,java,indent=0,,subs="attributes,specialchars"]
----
	@SpringBootTest(webEnvironment = WebEnvironment.NONE)
	@AutoConfigureStubRunner(
		ids = "io.spring.initializr:initializr-web:{spring-initializr-version}",
		repositoryRoot = "https://repo.spring.io/{initializr-repo}")
	class ClientApplicationTests {

		@Autowired
		private StubFinder stubFinder;


		...

	}
----

Here is JUnit 5-based 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:

[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{test-examples}/stub/ClientApplicationTests.java[tag=test]
----

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.2+json` (as recommended).



== 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 Spring 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
Spring 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.