Mock the Wire, with WireMock.NET: Simplifying API Testing in .NET

Cosmin Vladutu
5 min readFeb 12, 2025

--

Introduction

If you work in web development, chances are your applications rely heavily on services. If we are talking about microservices, serverless functions like Azure Functions or AWS Lambda, or old classical web services, it doesn’t matter in our current discussion, because all of them have the same meaning: they are external dependencies.

Now, since there are so many, I guess you can imagine how critical it is that they communicate seamlessly, and why contract testing is so important, but even if you don’t want to have this name in your ecosystem, for sure you want to write integration tests against your service without needing to think about the external dependencies, and here is how Wiremock.NET comes to the rescue.

For me, contract testing validates that the interactions between services meet agreed-upon specifications while integration tests test the integrity of a service, with all its dependencies being mocked.

Integration Testing vs. Contract Testing with Wiremock.NET

Wiremock.NET blurs the lines between integration and contract testing. You might argue that using Wiremock.NET is only integration testing, as you’re mocking dependencies. However, Wiremock.NET helps you to test more than just your service’s internal integrity: you can validate how it interacts with external services, so you can treat it as contract testing.

The Problem

A few years back, I was working on a Web API that performed several critical functions in response to client requests. Based on input parameters, the API needed to:

  1. Query a database for specific data.
  2. Make an external HTTP call to another service to enrich the data.
  3. Aggregate the results and send them to another service to trigger an email notification.
  4. Respond to the client with the final output.

It’s pretty clear how I could handle the database, but what to do with the external HTTP calls?

Solution

Current solution and challenges

From the legacy code, there was a mocking service with its database, which was used for integration tests by all the services from the department, but this for me sounded off:

  1. We were changing multiple external dependencies only with one, but, still external. If the shared service was down or misconfigured, our tests failed
  2. Performance: Tests sometimes experienced latency due to the external service’s response times, leading to longer CI/CD pipelines.
  3. Inability to simulate edge cases: The service was meant to be generic and used by multiple services, so it was pretty hard to simulate latency spikes or timeouts.

Wiremock.NET Solution

This “thing” is a NuGet based on mock4net (which is not maintained anymore), and it’s basically a copy of the Java-based project Wiremock.NET (as a friend would say: All the good things are implemented in Java first).

Let’s talk a little bit now about what we wanted to test:

  1. I wanted to test the happy flow,
  2. I wanted to test what happens if I get a 400 or a 500
  3. What happens if I get a delayed response because of the latency or if I get a timeout?

Pretty normal and simple scenarios, right? To see some code, as support for this article, I’ve created a GitHub repo in which I have an Azure function which starts an orchestration with 2 activities, each one calling an external service. This way I hope you’ll see that you can use it in any scenario that uses external calls.

  _server = WireMockServer.Start();

_server.Given(Request.Create()
.WithPath("/search")
.WithParam("q", "Iasi")
.UsingGet())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBodyAsJson(new[]
{
new Location (51.321, 0.123)
}));

This is all you need to mock an entry point in your service, that expects a city as input and returns a location with latitude and longitude and returns an Ok result. In the repo, you’ll also find how to add delays, bad responses, how to handle headers and so on.

Cool feature

A cool feature from my point of view is the ability to record and playback stubs.
In short, you can capture live traffic between a client and a real service, save those interactions as stubs, and then use them for testing purposes. This feature helps developers quickly generate mocks or stubs for their tests without manually defining every request and response. I must admit, I haven’t used them in production, since I like more the fluent way of writing the responses, but if I had complicated answers from my 3rd party I would have used it for sure.

How to record the traffic?

How to record the traffic and generate a stub with wiremock

As you can see, with a few lines of code you can record the mappings in a JSON file. The file will have a request-response node with everything you have in there: path, the verb (method) arguments, headers and so on.

Playback the saved mapping

Create a wiremock server which playback specific recording.

Alternatives

I know there are Postman Mock Servers that I could use, but it has limited flexibility and I found it difficult to use in automation.

Another alternative would have been Pact, which I remember had some brokers and you could create a contract between the client and my service so that both could have been developed in parallel, but it was a little bit too much for me. I didn’t need that, since the client was developed in the same team.
Wiremock.NET compared to Pact is more lightweight and it felt a little bit simpler.

Conclusion

Whatever tool you choose or whatever name you give to the test it doesn’t matter as long as you test the integrity of your service in the ecosystem you develop in your distributed world. Robust testing of these interactions is non-negotiable.

I personally didn't feel the need for something more than Wiremock.NET offered, and it is excellent for me due to its simplicity (so the learning curve for the team is slim to none). It works well from my experience with HTTP and GRPC calls and with a few lines of code you can test your failure handling.
Before using it, we had flaky tests due to our latency against the mocking service we developed. Using this NuGet we decoupled our service and we were able to use it in any testing frameworks (I tested it with xUnit and MSTest). Even if I know Pact is a little bit more powerful, it comes with a higher complexity on the setup, and in our case, we didn’t need it and want it. It was a good bet, since for the entire lifetime of the project we didn’t need to change the tool.

--

--

Cosmin Vladutu
Cosmin Vladutu

Written by Cosmin Vladutu

Software Engineer | Azure & .NET Full Stack Developer | Leader

No responses yet