eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

Partner – Diagrid – NPI (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

WireMock is a library for stubbing and mocking web services. It constructs an HTTP server that we can connect to as we would to an actual web service.

When a WireMock server is in action, we can set up expectations, call the service, and verify its behaviors.

2. Maven Dependencies

In order to take advantage of the WireMock library, we need to include this dependency in the POM:

<dependency>
    <groupId>org.wiremock</groupId>
    <artifactId>wiremock</artifactId>
    <version>3.9.1</version>
    <scope>test</scope>
</dependency>

3. Programmatically Managed Server

This section will cover how to manually configure a WireMock server, i.e., without the support of JUnit auto-configuration. We demonstrate the usage with a very simple stub.

3.1. Server Setup

First, we instantiate a WireMock server:

WireMockServer wireMockServer = new WireMockServer(String host, int port);

In case no arguments are provided, the server host defaults to localhost and the server port to 8080.

Then we can start and stop the server using two simple methods:

wireMockServer.start();

and:

wireMockServer.stop();

3.2. Basic Usage

We’ll first demonstrate the WireMock library with basic usage, where a stub for an exact URL without any further configuration is provided.

Let’s create a server instance:

WireMockServer wireMockServer = new WireMockServer();

The WireMock server must be running before the client connects to it:

wireMockServer.start();

The web service is then stubbed:

configureFor("localhost", 8080);
stubFor(get(urlEqualTo("/baeldung")).willReturn(aResponse().withBody("Welcome to Baeldung!")));

This tutorial makes use of the Apache HttpClient API to represent a client connecting to the server:

CloseableHttpClient httpClient = HttpClients.createDefault();

A request is executed, and a response is returned afterward:

HttpGet request = new HttpGet("http://localhost:8080/baeldung");
HttpResponse httpResponse = httpClient.execute(request);

We’ll convert the httpResponse variable to a String using a helper method:

String responseString = convertResponseToString(httpResponse);

Here is the implementation of that conversion helper method:

private String convertResponseToString(HttpResponse response) throws IOException {
    InputStream responseStream = response.getEntity().getContent();
    Scanner scanner = new Scanner(responseStream, "UTF-8");
    String responseString = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return responseString;
}

The following code verifies that the server has got a request to the expected URL and that the response arriving at the client is exactly what was sent:

verify(getRequestedFor(urlEqualTo("/baeldung")));
assertEquals("Welcome to Baeldung!", stringResponse);

Finally, we should stop the WireMock server to release system resources:

wireMockServer.stop();

4. JUnit Managed Server

This section illustrates the usage of a WireMock server with the help of JUnit 5. In JUnit 5, the @Rule annotation used in JUnit 4 is replaced by lifecycle methods, such as @BeforeEach and @AfterEach, or custom extensions.

4.1. Server Setup

Using lifecycle methods, we can manage the WireMock server’s lifecycle in JUnit test cases, ensuring the server starts before each test and stops after completion.

Similar to the programmatically managed server, we create a WireMock server as a Java object:

private WireMockServer wireMockServer;

@BeforeEach
void setup() {
    wireMockServer = new WireMockServer(WireMockConfiguration.options().port(port));
    wireMockServer.start();
    WireMock.configureFor("localhost", port);
}

@AfterEach
void teardown() {
    if (wireMockServer != null) {
        wireMockServer.stop();
    }
}

If no port is supplied, the server port will default to 8080. Server host, defaulting to localhost, and other configurations may still be specified using the Options interface.

4.2. URL Matching

After setting up a WireMock server instance, the next step is to configure a stub.

In this subsection, we’ll provide a REST stub for a service endpoint using a regular expression:

stubFor(get(urlPathMatching("/baeldung/.*"))
  .willReturn(aResponse()
  .withStatus(200)
  .withHeader("Content-Type", "application/json")
  .withBody("\"testing-library\": \"WireMock\"")));

Next, we create an HTTP client, execute a request, and capture the response:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

The above code snippet uses a helper method to convert the HttpResponse to a String:

private String convertHttpResponseToString(HttpResponse httpResponse) throws IOException {
    InputStream inputStream = httpResponse.getEntity().getContent();
    return convertInputStreamToString(inputStream);
}

This in turn makes use of another private method:

private String convertInputStreamToString(InputStream inputStream) {
    Scanner scanner = new Scanner(inputStream, "UTF-8");
    String string = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return string;
}

Finally, we verify the stub’s behavior using the following assertions:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
assertEquals("application/json", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("\"testing-library\": \"WireMock\"", stringResponse);

4.3. Request Header Matching

Now we will demonstrate how to stub a REST API by matching headers.

Let’s start with the stub configuration:

stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)
  .withHeader("Content-Type", "text/html")
  .withBody("!!! Service Unavailable !!!")));

Similar to the preceding subsection, we illustrate HTTP interaction using the HttpClient API, with help from the same helper methods:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
request.addHeader("Accept", "text/html");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

The following verification and assertions confirm functions of the stub we created before:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());
assertEquals("text/html", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("!!! Service Unavailable !!!", stringResponse);

4.4. Request Body Matching

We can also use the WireMock library to stub a REST API with body matching.

Here is the configuration for a stub of this kind:

stubFor(post(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json"))
  .withRequestBody(containing("\"testing-library\": \"WireMock\""))
  .withRequestBody(containing("\"creator\": \"Tom Akehurst\""))
  .withRequestBody(containing("\"website\": \"wiremock.org\""))
  .willReturn(aResponse()
  .withStatus(200)));

Now it’s time to create a StringEntity object that will be used as the body of a request:

InputStream jsonInputStream 
  = this.getClass().getClassLoader().getResourceAsStream("wiremock_intro.json");
String jsonString = convertInputStreamToString(jsonInputStream);
StringEntity entity = new StringEntity(jsonString);

The code above uses one of the conversion helper methods defined before, convertInputStreamToString.

Here is the content of the wiremock_intro.json file on the classpath:

{
    "testing-library": "WireMock",
    "creator": "Tom Akehurst",
    "website": "wiremock.org"
}

And we can configure and run HTTP requests and responses:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost request = new HttpPost("http://localhost:8080/baeldung/wiremock");
request.addHeader("Content-Type", "application/json");
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);

This is the testing code used to validate the stub:

verify(postRequestedFor(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json")));
assertEquals(200, response.getStatusLine().getStatusCode());

4.5. Stub Priority

The previous subsections deal with situations where an HTTP request matches only a single stub.

It’s more complicated if there is more than a match for a request. By default, the most recently added stub will take precedence in such a case.

However, users can customize that behavior to take more control of WireMock stubs.

We’ll demonstrate the operations of a WireMock server when a coming request matches two different stubs, with and without setting the priority level, at the same time.

Both scenarios will use the following private helper method:

private HttpResponse generateClientAndReceiveResponseForPriorityTests() throws IOException {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
    request.addHeader("Accept", "text/xml");
    return httpClient.execute(request);
}

First, we configure two stubs without consideration of the priority level:

stubFor(get(urlPathMatching("/baeldung/.*"))
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)));

Next, we create an HTTP client and execute a request using the helper method:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

The following code snippet verifies that the last configured stub is applied regardless of the one defined before when a request matches both of them:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());

Let’s move on to stubs with priority levels being set, where a lower number represents a higher priority:

stubFor(get(urlPathMatching("/baeldung/.*"))
  .atPriority(1)
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .atPriority(2)
  .withHeader("Accept", matching("text/.*"))
  .willReturn(aResponse()
  .withStatus(503)));

Now we’ll carry out the creation and execution of an HTTP request:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

The following code validates the effect of priority levels, where the first configured stub is applied instead of the last:

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());

5. Conclusion

This article introduced WireMock and how to set up as well as configure this library for testing of REST APIs using various techniques, including matching of URL, request headers and body.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=REST)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)