Tag Archives: testing

Introduction to Unit Tests (with examples in .Net) – Part 4 – Mocking (Including fakes and stubs)

In this, forth (and probably final) post on the subject of Unit Tests, we’re going to dive a little deeper into the subject of mocking. We’ll discuss what the difference is between a mock, a stub, and a fake; we’ll also talk about mocking frameworks.

A Fake, Stubby, Mock

These terms are often used interchangeably, and that’s fine – but they can mean different things. There are a couple of sources (that I could find) that have defined the difference between these terms:

Mocks Aren’t Stubs – an article from 2007 by Martin Fowler.

xUnit Test Patterns – a book on Unit Testing.

Broadly, they both say the same, which is this:

A Stub is a replacement for functionality that will return a given value without actually executing any life-like code.

A Mock is similar to a stub, but allows for analysis of that behaviour – for example, you can determine whether or not the method was called, or how many times.

A Fake is a replacement for functionality that is intended to mimic the actual functionality of the code.

A Test Double is a generic term to encompass all three.

Let’s have a look at an example for each. We’ll stick with manual test doubles for now. Let’s consider one of the manual mocks that we created in the last post:

    public class MockInputOutputWrapper : IInputOutputWrapper
    {
        private readonly string _inputValue;

        public MockInputOutputWrapper(string inputValue) =>
            _inputValue = inputValue;        

        public string GetInput(string prompt) => _inputValue;        

        public void Output(string text) { }
    }

Stub

Our first call is the stub, which is the Output method in the code above. It provides a method to call, but no functionality whatsoever.

Mock

Let’s imagine that we wanted to ascertain how many times we called Output – we may do something like this:

public class MockInputOutputWrapper : IInputOutputWrapper
{
    private readonly string _inputValue;
    private int _outputCount = 0;

    public MockInputOutputWrapper(string inputValue) =>
        _inputValue = inputValue;        

    public string GetInput(string prompt) => _inputValue;        

    public void OutputCallsMustBe(int count)
    {
        if (count != _outputCount) throw new Exception("Output Calls Incorrect");
    }

    public void Output(string text) 
    {
        _outputCount++;
    }
}

Now Output is a mock, rather than a stub. For this post, I won’t go to the extent of writing a mocking framework, but I think the code above illustrates the point. That is, we can ascertain that Output has been called, say, once:

[Fact]
public void Output_ValidGuess_CalledOnce()
{
    // Arrange
    var inputOutputWrapper = new MockInputOutputWrapper("12");
    var randomNumberChooser = new MockRandomNumberChooser();
    var sut = new Game(inputOutputWrapper, randomNumberChooser);

    // Act
    string result = sut.RunMethod();

    // Assert
    Assert.Equal("Well done, you guessed!", result);
    inputOutputWrapper.OutputCallsMustBe(1);
}

Finally, we’ll discuss what a fake is.

Fake

Fakes allow for functionality to be replicated in a way that’s more conducive to the test. The stub allowed us to essentially ignore the functionality altogether; the mock allowed us to assert that, despite replacing the functionality, it had actually been invoked (or would have been); the fake allows us to substitute that functionality. A good example here is a database – in order to test the interaction with a database, you may find it necessary to actually store some data in memory. Using our example, what if we needed to ascertain that the game dealt with different random numbers; we could write this:

[Fact]
public class MockRandomNumberChooser : IRandomNumberChooser
{
    private int[] _numberList = new[] { 12, 3, 43 };
    private int _index = 0;
    public int Choose() => _numberList[_index++];
}

Now that we understand the difference, we’ll see that it can be very academic, especially when dealing with mocking frameworks.

There’s a lot of boiler plate code here. Manually creating these classes does the job, but imagine the following scenario: you have 5 different mock classes, and you add a method to the interface IRandomNumberChooser. You now need to manually go through each of those mocks and add the functionality necessary to mock out the new function – you are very likely to not care about the new function in most of those methods, but nevertheless, you would need to go and honour the interface.

Mocking Frameworks

Mocking frameworks aim to solve this problem by creating a mechanism to mock or subclass an object. There are currently two main mocking frameworks for .Net: Nsubstitute and Moq. There’s also Microsoft Fakes.

We won’t cover all of these, and the principle behind them is broadly the same, with a slightly different implementation bias. I’ve always found NSubstitute much more intuitive, so we’ll cover that.

We’ll start by simply deleting the MockRandomNumberChooser. Now install Nsubstitute:

Install-Package NSubstitute

The next part is to simply tell NSubstitute to do the same thing that you had done using the mock class:

var randomNumberChooser = Substitute.For<IRandomNumberChooser>();
randomNumberChooser.Choose().Returns(12);

If you run the test, you’ll see absolutely no difference. Based on our discussion earlier in the post, we have created a stub, but we can create both Mocks and Fakes using the same class. If you want to create a mock, you’ll do so like this:

randomNumberChooser.Received(1).Choose();

Fakes are a little different, however, you can still replace the functionality.

References

https://www.pmichaels.net/2018/03/22/using-nsubstitute-for-partial-mocks/

https://github.com/nsubstitute/NSubstitute/

https://github.com/moq

WireMock.Net

I was recently introduced to the WireMock.Net package. This is a .Net implementation of WireMock.

The basic idea where is that you can mock or stub a HTTP call. For example, you can tell it that when https://localhost:1234/test is called then a specific response should be returned – you could, for example, force it to error.

To get started, install the package:

install-package wiremock.net

This is a hefty package, so make sure it’s restricted to your test project.

The following code will replace the URL above with a response of “aaa”:

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

Console.WriteLine("Hello, World!");


var request = Request.Create()    
    .WithPath("/test")
    .UsingGet();

var response = Response.Create()
    .WithStatusCode(200)
    .WithBody("aaa");

WireMockServer wireMockServer = WireMockServer.Start(1234);
wireMockServer
    .Given(request)
    .RespondWith(response);


HttpClient client = new HttpClient();
var result = await client.GetAsync("http://localhost:1234/test");
if (result != null && result.IsSuccessStatusCode)
{
    var output = await result.Content.ReadAsStringAsync();
    Console.WriteLine(output);
}

I did, at first, try to run this for an actual site (e.g. to intercept google.com or something), but it won’t allow that, only localhost (at least, as far as I could see). A friend at work pointed out that, in a test, you would pass the URL in through the config anyway, and so you could change it to localhost.

References

https://pcholko.com/posts/2021-04-05/wiremock-integration-test/

Cyclomatic Complexity – What it is, why you should care, and how to reduce it using the Strategy Pattern

Cyclomatic complexity is one of those terms that makes you think you missed something when you were learning programming. However, the concept is a really simple one. Cyclomatic complexity is simply the number of paths through your code. There are more detailed explanations if you scan the web (involving edges and nodes), but for this post, we’ll just work with that.

Code Metrics

This article is not about .Net per se – what I’m writing here applies to any OO language; however, for the purpose of illustration, I’ll be using C#, and the Code Metrics Window in Visual Studio.

Cyclomatic Complexity

Given what we’ve just said, we can take the following program:

int x = 1;

And we can determine that the cyclomatic complexity is 1 – that is, there is only one way that this code can execute – no branches, no loops, just one statement. So, the cyclomatic complexity is 1:

Okay, let’s now add a single branch:

There are now two ways this code can execute (in actuality, there is only one, but cyclomatic complexity doesn’t follow the actual logical course – so let’s agree on two for the sake of argument).

We can now add a second condition:

The complexity now goes to three.

Okay, so that’s all very interesting, but what does that actually mean – why is it useful to know this number? The main answer to this is testability: if you know there are 3 possible execution paths for the code, then you know that you need a minimum of 3 tests to cover those paths. There’s a second part to that, which is that a method that requires one – three tests might be easy to change or debug, one that requires ten – twenty tests is definitely not.

So, the question is, how can we reduce this figure?

Reducing Cyclomatic Complexity

There are, obviously, more answers to this than would fit in this post, but here I’m going to focus on bringing in a strategy pattern.

Let’s consider the following code:

    // Night
    switch (thingToAutomate)
    {
        case "Door":
            Console.WriteLine("Lock");
            break;

        case "Window":
            Console.WriteLine("Close");
            break;

        case "TV":
            Console.WriteLine("Turn off");
            break;

        case "Lights":
            Console.WriteLine("Turn off");
            break;
    }

This method had a cyclomatic complexity of 5 – there are 4 options, but also the possibility that none are true.

The essence behind the strategy pattern is just that you assign functionality using polymorphism. If we consider the code above, doing that would actually increase the number of lines of code, and thereby increase the cyclomatic complexity. However, what if, in addition to the automation routine at night, we needed one for the morning:

// Morning
switch (thingToAutomate)
{
    case "Door":
        Console.WriteLine("Unlock");
        break;

    case "Window":
        Console.WriteLine("Open");
        break;

    case "TV":        
    case "Lights":        
        break;
}

Okay, now our cyclomatic complexity increases (to 9) – and will increase every time we need to vary our behaviour based on the thing that we’re automating. Instead, let’s consider the following:

    internal interface IThingToAutomateStrategy
    {
        void Morning();
        void Night();
    }

Let’s now imagine that we implement the interface for each thing:

    internal class Door : IThingToAutomateStrategy
    {
        public void Morning()
        {
            Console.WriteLine("Unlock");
        }

        public void Night()
        {
            Console.WriteLine("Lock");
        }
    }

    . . .

Admittedly, this does increase the lines of code, but we end up with simpler code, and it has a lower, overall, cyclomatic complexity:

    internal class Automation
    {
        public IThingToAutomateStrategy AutomateStrategy { get; set; }

        public void AutomateMorning()
        {
            AutomateStrategy.Morning();            
        }

        public void AutomateNight()
        {
            AutomateStrategy.Night();
        }
    }

We can then use this in our program like this:

IThingToAutomateStrategy automateStrategy;

switch (thingToAutomate)
{
    case "Door":
        automateStrategy = new Door();
        break;

    case "Window":
        automateStrategy = new Window();
        break;

    case "TV":
        automateStrategy = new TV();
        break;

    case "Lights":
        automateStrategy = new Lights();
        break;
}

automateStrategy.Morning();
automateStrategy.Night();

The cyclomatic complexity of this is back to 5; but the best part is that it doesn’t increase. Imagine the following new method:

    internal interface IThingToAutomateStrategy
    {
        void Morning();
        void Darkness();
        void Night();
    }

And the implementation:

    internal class Lights : IThingToAutomateStrategy
    {
        public void Darkness()
        {
            Console.WriteLine("Switch on");
        }

        public void Morning()
        {
            // Nothing to do here
        }

        public void Night()
        {
            Console.WriteLine("Turn Off");
        }
    }

It’s worth pointing out that we’re in breach of the ISP here – but since we’re only doing it to make a point, we’ll agree to let it slide.

Adding this to the code flow doesn’t affect the cyclomatic complexity score of that code file at all:

IThingToAutomateStrategy automateStrategy;

switch (thingToAutomate)
{
    case "Door":
        automateStrategy = new Door();
        break;

    case "Window":
        automateStrategy = new Window();
        break;

    case "TV":
        automateStrategy = new TV();
        break;

    case "Lights":
        automateStrategy = new Lights();
        break;
}

automateStrategy.Morning();
automateStrategy.Darkness();
automateStrategy.Night();

It’s worth noting that it does increase the overall complexity, as it counts as a single additional code path per thing.

References

https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-cyclomatic-complexity?WT.mc_id=DT-MVP-5004601

https://docs.microsoft.com/en-us/visualstudio/code-quality/how-to-generate-code-metrics-data?WT.mc_id=DT-MVP-5004601

https://codinghelmet.com/articles/reduce-cyclomatic-complexity-composite-design-pattern

https://www.c-sharpcorner.com/UploadFile/shinuraj587/strategy-pattern-in-net/

https://codewithshadman.com/strategy-pattern-csharp/

https://github.com/pcmichaels/StrategyExample

Manually Adding DbContext for an Integration Test

In EF Core, there is an extension method that allows you to add a DBContext, called AddDBContext. This is a really useful method, however, in some cases, you may find that it doesn’t work for you. Specifically, if you’re trying to inject a DBContext to use for unit testing, it doesn’t allow you to access the DBContext that you register.

Take the following code:

services.AddDbContext<MyDbContext>(options =>
                options.UseSqlServer());
         

I’ve previously written about using UseInMemoryDatabase. However, this article covered unit tests only – that is, you are able to instantiate a version of the DBContext in the unit test, and use that.

As a reminder of the linked article, if you were to try to write a test that included that DBContext, you might want to use an in memory database; you might, therefore, build up a DBContextOptions like this:

var options = new DbContextOptionsBuilder<MyDbContext>()
                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                .EnableSensitiveDataLogging()
                .Options;
var context = new MyDbContext(options);

But in a scenario where you’re writing an integration test, you may need to register this with the IoC. Unfortunately, in this case, AddDbContext can stand in your way. The alternative is that you can simply register the DbContext yourself:

var options = new DbContextOptionsBuilder<MyDbContext>()
                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                .EnableSensitiveDataLogging()
                .Options;
var context = new MyDbContext(options);
AddMyData(context);
services.AddScoped<MyDbContext>(_ => context);

AddMyData just adds some data into your database; for example:

private void AddTestUsers(MyDbContext context)
{            
    MyData data = new MyData()
    {
        value1 = "test",
        value2 = "1"                
    };
    context.MyData.Add(subject);
    context.SaveChanges();
}

This allows you to register your own, in memory, DbContext in your IoC.

Chaos Monkey – Part 1 – Simulating a dodgy network on a local IIS

I thought I’d share this little DOS script that I’ve been using to simulate an unstable network connection on a local IIS:

:startLoop
	iisreset
	ping 1.1.1.1 -n 1 -w 10000 > nul
	GOTO startLoop
:endLoop

Not rocket science, but it does what it says on the tin. I saved it into a batch file and run that along with my app.