C# Advent: WireMock.Net

For the past few years I have mostly been testing backend services written in Java. But now that I’ll be working more in Unity, I wanted to see if one of my favorite Java testing libraries, WireMock, is available for C# development. WireMock allows you to set up a mock HTTP service at run-time with request matching and pre-set responses. If you need to write tests with any kind of micro-service or other HTTP dependencies, then WireMock is an invaluable tool for setting up fast and reliable mock responses. Thankfully, a port is available for .Net development: WireMock.Net!

If you have used the original WireMock, then WireMock.Net is very similar. But if you haven’t, here is a quick overview of how it works.

First let’s set up a little bit of code to test (Full code available here):

namespace WireMockSample
{
    public class SimpleServiceCaller
    {
        private readonly string _baseUrl;
        public SimpleServiceCaller(string baseUrl){
            _baseUrl = baseUrl;
        }
        public SimpleLoginResponse DoSimpleLogin(string userName)
        {
            var client = new RestClient(_baseUrl);
            var request = new RestRequest("/player/startSession", Method.POST);
            request.RequestFormat = DataFormat.Json;
            request.AddBody(new SimpleLoginRequest
            {
                userName = userName
            });
            var response = (RestResponse)client.Execute(request);
            SimpleLoginResponse loginResponse = null;
            if (response.IsSuccessful)
            {  
                loginResponse = JsonConvert.DeserializeObject<SimpleLoginResponse>(response.Content);
            }
            else
            {
                if (response.StatusCode.Equals(HttpStatusCode.Forbidden))
                {
                    loginResponse = new SimpleLoginResponse
                    {
                        error = "Forbidden User"
                    };
                }
            }
            

            return loginResponse;
        }
    }

    public class SimpleLoginRequest
    {
        public string userName;
    }

    public class SimpleLoginResponse
    {
        public int id;
        public string userName;
        public string error;
    }
}

This is just a simple class that uses RestSharp to make a POST request to another service. A simple integration test might look like this:

[Test]
[Ignore("only works on my machine")]
/*
 * This will only work if you happen to
 * have a version of the target service
 * running at localhost port 8787
 */
public void TestSimpleLogin()
{
    var caller = new SimpleServiceCaller("http://localhost:8787");
    var userId = Guid.NewGuid().ToString().Replace("-", "");
    var response = caller.DoSimpleLogin(userId);
    Assert.AreEqual(userId, response.userName);
}

The problem with this, of course is that it depends on the actual service running somewhere, which is not practical for unit testing or a CI pipeline. But WireMock.Net is here to help us out!

Setup

The first step is to download and install the package from NuGet. Then add the following using directives:

using WireMock.Matchers;
using WireMock.Server;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;

Starting the service is very simple. By default, WireMock dynamically allocate its own ports, so you will need to get the generated URL to pass to your calling object.

private static FluentMockServer _mockServer;
private static SimpleServiceCaller _simpleCaller;

[TestFixtureSetUp]
public static void SetUpWireMock()
{
    _mockServer = FluentMockServer.Start();
    // WireMock selects its own ports, so just grab the first
    // generated URL string
    _simpleCaller = new SimpleServiceCaller(_mockServer.Urls.First());
}

You only need to have one running service for each TestFixture.

Request Matching

Once the mock server is running, you can set up stub responses based on a variety of request matching strategies. In this case, the StubLogin method is using a JsonMatcher, which matches incoming request against a given JSON object. Requests can also be matched against the path, query parameters, or header values.

private static void StubLogin(string testUser, int expectedId)
{
    var canned = new SimpleLoginResponse
    {
        userName = testUser,
        id = expectedId,
        currentLevel = 0,
        maxLevel = 1

    };
    _mockServer
          .Given(Request
            .Create().WithPath("/player/startSession")
            // The canned response will *only* be sent to the 
            // request with the corresponding userName
            .WithBody(new JsonMatcher("{ \"userName\": \"" + testUser + "\" }"))
            .UsingPost())
          .RespondWith(
            Response.Create()
              .WithStatusCode(200)
              .WithHeader("Content-Type", "application/json")
            .WithBodyAsJson(canned)
          );

}

WireMock.Net also supports Linq, Regex, and XPath matching along with several others. Unfortunately, WireMock.Net has not caught up to the Java version in that custom request matchers are not supported. Still, the provided matchers will cover most common service scenarios. More information on WireMock.Net request matchers here.

Testing with WireMock.Net

Once your service is set up, you can use your mock service just as if it was the real running service.

Basic Test

[Test]
/*
 * This will work anytime, anywhere!
 */
public void TestSimpleLoginWireMock()
{
    var userId = Guid.NewGuid().ToString();
    StubLogin(userId, 42);
    var response = _simpleCaller.DoSimpleLogin(userId);
    Assert.AreEqual(userId, response.userName);
    // predictable id!
    Assert.AreEqual(42, response.id);

}

HTTP Failure Test

Testing if your code works when other services fail is easy with WireMock.Net!

[Test]
/*
 *  Mocking error conditions is simple
 */
public void TestLoginFailureWireMock()
{
    // Note that because the failure is tied to a specific userName,
    // the other tests will still function properly
    _mockServer
        .Given(Request
            .Create().WithPath("/player/startSession")
            // The canned response will *only* be sent to the 
            // request with the corresponding userName
            .WithBody(new JsonMatcher("{ \"userName\": \"BADWOLF\" }"))
            .UsingPost())
        .RespondWith(
            Response.Create()
                .WithStatusCode(HttpStatusCode.Forbidden)
        );
    
    
    var response = _simpleCaller.DoSimpleLogin("BADWOLF");
    Assert.AreEqual("Forbidden User", response.error);

}

Note that you can also set up a scenario where all requests are accepted *except* the failure case by using MatchBehaviour.RejectOnMatch. 

Other Testing Scenarios

  • Unit testing a client when the services it depends on aren’t ready yet
  • Fast UI testing with mocked service calls
  • Setting up test players with mock authentication
  • Simulating slow response or service outages
  • WireMock.Net.Standalone as a stand-alone mock service for CI/CD pipelines
  • Many many more!

I’ve used WireMock for many years in testing Java services, so I’m very happy that it is available for DotNet. I hope you will take a look and see how it can expand your testing repertoire as well!

 

Using JMeter Properties from the Command Line

It says it right there when you start JMeter: Don’t use GUI mode for load testing !, only for Test creation and Test debugging.”

Don't use GUI mode for load testing !
JMeter Startup Message

The JMeter developers were even kind enough to include an example of how to call JMeter on the command line:

jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]

This is a good start, but the real power in running JMeter from the terminal comes when you can set your test parameters at run time by passing them as properties. For example, you might want to run the same scenario with various thread counts or for a different number of iterations. You can even use command-line properties to toggle multiple test scenarios. Continue reading “Using JMeter Properties from the Command Line”

POST/CON 2018

POST/CON 2018

Back in the spring of 2016 I did my very first talk for STPCon. It was about testing REST services and I mentioned Postman as a good tool for exploring services; saying in passing, “I could probably do a whole talk just on Postman”. Since then I have done multiple talks and workshops on the Postman tool, so when I saw that Postman the company was doing its first ever conference in essentially my backyard, I had to throw my hat in the ring as a speaker.

I was pretty excited about this conference both as a chance to meet the Postman team and also because it would be my first time stepping out of the test conference bubble and meeting with a whole different group of people. In that regard, POST/CON 2018 definitely lived up to my expectations. I had a great time talking with people from all sorts of different roles, not just testing. Below is a brief overview of the program with some highlights: Continue reading “POST/CON 2018”

Testing with Naughty Strings in Postman

Testing with Naughty Strings in Postman

Postman is a great tool for exploratory testing and the Big List of Naughty Strings (BLNS) is a great resource for exploratory testing, so I wanted to put the two things together into a Reese’s Peanut Butter Cup of tasty test flavor.

Step One: Getting the Naughty Strings

My plan was to use the Collection Runner to put each naughty string into my chosen API parameter. To do that, I would need a list of strings in a csv format. The BLNS repo includes a couple files with the strings encoded as base64, which is necessary for the csv parser, so my first quick and dirty solution was just to cut and paste the strings from blns.base64.json into a text file, slap a header on top and save it as a csv. Continue reading “Testing with Naughty Strings in Postman”

A Little Agile Night Music

A Little Agile Night Music

From the ages of 9 to 18 I dedicated at least an hour most days to practicing the cello. I was far from a prodigy, but with work, private lessons, and endless nagging by my mother, I was able to achieve a moderately high level of mediocre. Seattle has one of the best youth symphony orchestra organizations in the country and for two years I played in the top level orchestra. I was clinging by my fingernails to the very back of the section, but I was there, nonetheless

It has been 30 years since I played the cello seriously, but I find many parallels between my experiences as a cellist and my career as a software tester. Being in a siloed test team, such as the ones I experienced at Microsoft, is like playing in an orchestra. Ideally, the different sections work in concert towards a shared goal, watching management for cues on where to put the most effort. But there isn’t very much communication between the dev and test teams. At my last Microsoft position, the dev and test teams were on completely different floors, so we didn’t even see each other in the break room. Continue reading “A Little Agile Night Music”

Creating Weighted Flows in JMeter

It is pretty common for applications to have multiple flow paths. For example, it is common in mobile games to have one call flow for players that have authenticated with Facebook and a very different one for anonymous players. When trying to replicate a realistic server load in JMeter, it is important to be able to handle these different paths that users take through the client application.

JMeter actually has this capability right out of the box, no Groovy scripting or secondary plugins needed. With a Random Variable and a few If Controllers, you can enable any number of different flow paths in your load testing script. Continue reading “Creating Weighted Flows in JMeter”