Skip to content

Commit

Permalink
Updated Spring Boot integration docs (#322)
Browse files Browse the repository at this point in the history
* Added a new doc page for the Spring Boot integration and tweaked the Spring solution page

* Various tweaks to Spring boot URLs and links

* Fixed missing closing brace in code sample

* Updated Spring Boot integration version and fixed its variable name
  • Loading branch information
tomakehurst authored Dec 2, 2024
1 parent bfedda9 commit 6201983
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 38 deletions.
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ wiremock_baseline: 3.x
pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/

grpc_extension_version: 0.8.1
spring_boot_integration_version: 3.3.0

community_slack:
join_url: https://slack.wiremock.org/
Expand Down
7 changes: 6 additions & 1 deletion _data/doc-categories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ java:
pages:
- junit-jupiter
- junit-extensions
- spring-boot
- spring-boot-integration
- java-usage
- configuration
- running-without-http-server
Expand Down Expand Up @@ -64,6 +64,11 @@ protocols:
- jwt
- https

integrations:
title: Integrations
pages:
- spring-boot

configuration:
title: Advanced use-cases
pages:
Expand Down
2 changes: 1 addition & 1 deletion _docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ <h2>By technology</h2>
<img src="{{ '/images/logos/technology/python.svg' | absolute_url }}" />
Python
</a>
<a class="card" href="./spring-boot">
<a class="card" href="./solutions/spring-boot-integration">
<img src="{{ '/images/logos/technology/spring.svg' | absolute_url }}" />
Spring Boot
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,33 @@
layout: solution
title: "Using WireMock with Spring Boot"
meta_title: Running WireMock with Spring Boot | WireMock
toc_rank: 116
description: The team behind Spring Cloud Contract have created a library to support running WireMock using the “ambient” HTTP server
redirect_from:
- "/docs/spring-boot.html"
logo: /images/logos/technology/spring.svg
hide-disclaimer: true
---

<div class="cloud-callout"><a href="https://www.wiremock.io?utm_source=oss-docs&utm_medium=oss-docs&utm_campaign=cloud-callouts-solutionspringboot&utm_id=cloud-callouts&utm_term=cloud-callouts-solutionspringboot" target="_BLANK">Centralize and scale your API mocks with WireMock Cloud.</a></div>

<div class="cloud-callout"><a href="https://www.wiremock.io?utm_source=oss-docs&utm_medium=oss-docs&utm_campaign=cloud-callouts-solutionsspringboot&utm_id=cloud-callouts&utm_term=cloud-callouts-solutionsspringboot" target="_BLANK">Centralize and scale your API mocks with WireMock Cloud.</a></div>

## WireMock Spring Boot

[WireMock Spring Boot](https://github.com/wiremock/wiremock-spring-boot)
simplifies testing HTTP clients in Spring Boot & Junit 5 based integration tests.
It includes fully declarative WireMock setup,
supports multiple `WireMockServer` instances,
automatically sets Spring environment properties,
and does not pollute Spring application context with extra beans.

Example:
WireMock's official Spring Boot integration library is the simplest way to configure Spring Boot, Junit 5 and WireMock to work together.

```java
@SpringBootTest
@EnableWireMock
class DefaultInstanceTest {

@Value("${wiremock.server.baseUrl}")
private String wiremockUrl;
It includes fully declarative WireMock setup, supports multiple `WireMockServer` instances, automatically sets Spring environment properties,
and does not pollute Spring application context with extra beans.

@Test
void returnsTodos() {
WireMock.stubFor(get("/ping")
.willReturn(aResponse()
.withStatus(200)));
See [WireMock Spring Boot Integration](/docs/spring-boot/) for details on installation and usage.

RestAssured
.when()
.get(this.wiremockUrl + "/ping")
.then()
.statusCode(200);
}
}
```
You can contribute or log an issue in the [GitHub project](https://github.com/wiremock/wiremock-spring-boot).

## Spring Cloud Contract

The team behind Spring Cloud Contract have created a library to support running WireMock using the "ambient" HTTP server.
It also simplifies some aspects of configuration and eliminates some common issues that occur when running Spring Boot and WireMock together.
WireMock provides the mocking capabilities for the Spring Cloud Contract project (a consumer-driven contract testing tool).

See [Spring Cloud Contract WireMock](https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/project-features.html#features-wiremock) for details.

The article [Faking OAuth2 Single Sign-on in Spring](https://engineering.pivotal.io/post/faking_oauth_sso/)
from Pivotal's blog shows how WireMock can be used to test Spring apps that use 3rd party OAuth2 login.


## Jetty version issues when running WireMock and Spring together.

WireMock's main artifact is built on Jetty 11, largely so that Java 11 support can be maintained. However, many Spring applications depend on Jetty 12 and the presence of both on the classpath causes WireMock to fail with a `ClassNotFoundException` or `NoClassDefFoundError` for Servlet API classes thrown during startup.
Expand Down
237 changes: 237 additions & 0 deletions _docs/spring-boot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
---
layout: docs
title: "WireMock Spring Boot Integration"
meta_title: Using WireMock's Spring Boot + JUnit 5 integration | WireMock
description: Integrating WireMock, Spring Boot and JUnit 5 via the official integration library.
---

WireMock's Spring Boot integration provides a simple, declarative way to configure and run one or more WireMock instances their JUnit tests.

## Installation

Maven:
```xml
<dependency>
<groupId>org.wiremock.integrations</groupId>
<artifactId>wiremock-spring-boot</artifactId>
<version>{{ site.spring_boot_integration_version }}</version>
</dependency>
```

Gradle:
```groovy
implementation 'org.wiremock.integrations:wiremock-spring-boot:{{ site.spring_boot_integration_version }}'
```

## Basic usage

The integration is enabled by adding the `@EnableWireMock` annotation to your test class.

```java
@SpringBootTest(classes = ExamplesTests.AppConfiguration.class)
@EnableWireMock
class ExampleTests {

@Value("${wiremock.server.baseUrl}")
private String wireMockUrl;

@Test
void returns_a_ping() {
stubFor(get("/ping").willReturn(ok("pong")));

RestClient client = RestClient.create();
String body = client.get()
.uri(wireMockUrl + "/ping")
.retrieve()
.body(String.class);

assertThat(body, is("pong"));
}

@SpringBootApplication
static class AppConfiguration {}
}
```

### Injected properties

The example above will start a WireMock instance with a sensible set of defaults and set the following properties in the Spring context:

- `wiremock.server.baseUrl` - Base URL of WireMock server.
- `wiremock.server.port` - HTTP port of WireMock server.

These property names can be changed as follows:

```java
@EnableWireMock(
@ConfigureWireMock(
baseUrlProperties = { "customUrl", "sameCustomUrl" },
portProperties = "customPort"
))
class CustomPropertiesTest {

@Value("${customUrl}")
private String customUrl;

@Value("${sameCustomUrl}")
private String sameCustomUrl;

@Value("${customPort}")
private String customPort;

// ...
}
```


## Declarative configuration
A number of WireMock's common configuration values can be overridden via the `@ConfigureWireMock` annotation, which is used as follows:

```java
@EnableWireMock({
@ConfigureWireMock(
name = "my-mock",
port = 8888
})
```

This currently supports the following config items:

* `port`: the HTTP port number. Defaults to 0 i.e. random.
* `httpsPort`: the HTTPS port number. Defaults to 0 i.e. random.
* `name`: the WireMock instance name. It is usually a good idea to set this when running multiple WireMock instances. Defaults to `wiremock`.
* `usePortFromPredefinedPropertyIfFound`: if true, take the port number from the Spring configuration. Defaults to false.
* `portProperties`: Overrides for the HTTP port property name.
* `httpsPortProperties`: Overrides for the HTTPS port property name.
* `baseUrlProperties`: Overrides for the HTTP base URL property name.
* `httpsBaseUrlProperties`: Overrides for the HTTPS base URL property name.
* `filesUnderClasspath`: Classpath root that will be used as the WireMock instance's file source. See [Customizing the mappings directory](#customizing-the-mappings-directory) for details.
* `filesUnderDirectory`: File root that will be used as the WireMock instance's file source. See [Customizing the mappings directory](#customizing-the-mappings-directory) for details.
* `extensions`: WireMock extensions to be loaded, specified as class names.
* `extensionFactories`: WireMock extension factories to be loaded, specified as class names.
* `configurationCustomizers`: Customizer classes to be applied to the configuration object passed to the WireMock instance on construction. See [Programmatic configuration](#programmatic-configuration) for details.



## Programmatic configuration
If full control over the WireMock server's configuration is needed you can supply a customizer class that can call methods directly on the
WireMock configuration object.

```java
@EnableWireMock({
@ConfigureWireMock(
configurationCustomizers = CustomizerTest.Customizer.class)
})
public class CustomizerTest {

static class Customizer implements WireMockConfigurationCustomizer {

@Override
public void customize(
WireMockConfiguration configuration,
ConfigureWireMock options
) {
configuration.notifier(new CustomNotifier());
}
}
}
```



## Customizing the mappings directory
By default, each `WireMockServer` is configured to load WireMock root from:

1. Classpath *if specified*
1. `{specified-resource-name}/{server-name}`
2. `{specified-resource-name}`
2. Directory
1. `{CWD}/wiremock/{server-name}`
2. `{CWD}/stubs/{server-name}`
3. `{CWD}/mappings/{server-name}`
4. `{CWD}/wiremock`
5. `{CWD}/stubs`
6. `{CWD}/mappings`

This can be changed as follows:

```java
@EnableWireMock({
@ConfigureWireMock(
name = "fs-client",
filesUnderClasspath = "some/classpath/resource",
filesUnderDirectory = "or/a/directory")
})
```

## Injecting WireMock instances into the test
Sometimes it's necessary to gain programmatic access to a running WireMock instance e.g. to configure stubs or perform verifications.
To enable this you can inject the WireMock server into a field on the test class as follows:
```java
@SpringBootTest(classes = InjectionTest.AppConfiguration.class)
@EnableWireMock
public class InjectionTest {
@InjectWireMock
WireMockServer wireMock;
}
```
As described in the next section you can also specify the name of the desired instance when injecting:
```java
@SpringBootTest(classes = InjectionTest.AppConfiguration.class)
@EnableWireMock({
@ConfigureWireMock(name = "user-service")
})
public class InjectionTest {
@InjectWireMock("user-service")
WireMockServer mockUserService;
@Test
void fetch_empty_list_of_users() {
mockUserService.stubFor(get("/users").willReturn(okJson("[]")));
// ...
}
}
```
## Running multiple instances
It's typically a good idea to run a WireMock instance per API you wish to mock, primarily to avoid clashes in the URL schemes of the two (or more) APIs.

The Spring Boot integration supports this explictly via annotation configuration. By adding more than one configuration item, multiple instances will be
started and the associated properties added to the Spring context.

These instances can then be injected as fields on the test class to


```java
@SpringBootTest(classes = WireMockSpringExtensionTest.AppConfiguration.class)
@EnableWireMock({
@ConfigureWireMock(
name = "user-service",
baseUrlProperties = "user-service.url",
portProperties = "user-service.port"),
@ConfigureWireMock(
name = "todo-service",
baseUrlProperties = "todo-service.url",
portProperties = "todo-service.port")
})
public class WireMockSpringExtensionTest {

@SpringBootApplication
static class AppConfiguration {}

@InjectWireMock("user-service")
private WireMockServer mockUserService;

@InjectWireMock("todo-service")
private WireMockServer mockTodoService;
}
```

0 comments on commit 6201983

Please sign in to comment.