Category 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

Introduction to Unit Tests (with examples in .Net) – Part 3 – Test Frameworks and Manual Mocks

So far, in this series of posts on the basics of unit tests, we’ve spoken about concepts and methodologies, but we’ve steered away from using any specific frameworks or tools. In this post, we’ll investigate what a test framework can do for us.

We’ll continue to work with the code that we created in the previous post, but we’ll address the issues that we still had at the end of that post.

A Recap of the Story So Far

At the end of the previous post, we had the following code:

for (int i = 1; i <= 100; i++)
{
    // Arrange
    Func<string> mockInput = () => "5";
 
    // Act
    string result = RunMethod(mockInput);
 
    // Assert
    if (result == "Well done, you guessed!")
    {
        Console.WriteLine("Test Passed");
        break;
    }
}
 
for (int i = 1; i <= 100; i++)
{
    // Arrange
    Func<string> mockInput = () => "5";
 
    // Act
    string result = RunMethod(mockInput);
 
    // Assert
    if (result.StartsWith("Sorry, that was the wrong number"))
    {
        Console.WriteLine("Test Passed");
        break;
    }
}
 
{
    // Arrange
    Func<string> mockInput = () => "";
 
    // Act
    string result = RunMethod(mockInput);
 
    // Assert
    if (result == "Invalid guess")
    {
        Console.WriteLine("Test Passed");
    }
}

We had yet to introduce any tools or frameworks, but we had managed to test our code. We still had the following issues, however:

1. The tests passed, but we visually have to visually ascertain that.
2. We were outputting to the console needlessly.
3. Our tests were not resilient – a change of a single character in the user output, and the tests would break.
4. The tests were not deterministic – they were dependent on the result of a pseudo random number.

In this post, we’ll address these issues in order (apart from the third one, but we’ll come back to that) : we’ll start with the first.

1. The tests passed, but we visually have to visually ascertain that

How can we ascertain the result of a test without watching to see what happens with the test. One thing we could do is something similar to the following:

int RunTest1()
{
    for (int i = 1; i <= 100; i++)
    {
        // Arrange
        Func<string> mockInput = () => "5";

        // Act
        string result = RunMethod2(mockInput);

        // Assert
        if (result == "Well done, you guessed!")
        {
            Console.WriteLine("Test Passed");
            return 0;
        }
    }
    return 1;
}

int RunTest2()
{
    for (int i = 1; i <= 100; i++)
    {
        // Arrange
        Func<string> mockInput = () => "5";

        // Act
        string result = RunMethod2(mockInput);

        // Assert
        if (result.StartsWith("Sorry, that was the wrong number"))
        {
            Console.WriteLine("Test Passed");
            return 0;
        }
    }
    return 1;
}

int RunTest3()
{
    // Arrange
    Func<string> mockInput = () => "";

    // Act
    string result = RunMethod2(mockInput);

    // Assert
    if (result == "Invalid guess")
    {
        Console.WriteLine("Test Passed");
        return 0;
    }
    return 1;
}

Console.WriteLine(RunTest1());
Console.WriteLine(RunTest2());
Console.WriteLine(RunTest3());

There’s a lot of code here, but all we’ve actually done is wrap the tests up in functions, and then returned a value based on the result of the test. This means that we can write something like this:

if (RunTest1() != 0 | RunTest2() != 0 | RunTest3() != 0)
{
    Console.WriteLine("Some tests failed");
}

In case you didn’t know, the single pipe (|) in C# in a bitwise or – that is, it will execute all conditions regardless of the result and then evaluate the result, a logical or (||) would only run the tests until one failed and then exit the condition.

This approach also helps with the second issue.

2. We were outputting to the console needlessly

We’re outputting to the console for two reasons: the first is to validate the tests; we can now simply remove all of those from the test, since we have an actual value that we can test against. The second reason is that the code itself outputs to the console. As has been mentioned in a previous post, there are ways to redirect the output of the console without mocking it; however, I’m trying to keep this series generic, and that is specific to the .Net console (although I strongly suspect that most languages provide a similar concept).

To get around this, we could replicate what we did in the second post; however, we can also take a slightly different approach and wrap the entire input / output functionality in its own class; for example:

    internal class ConsoleInputOutputWrapper
    {
        public void Output(string text) => Console.WriteLine(text);
        public string GetInput(string prompt)
        {
            Output(prompt);
            return Console.ReadLine();
        }
    }

This idea gives us some additional benefits – as you can see, we already have the prompt and input in a single method; and we could go further – we could do some validation inside the method, too; what if the user doesn’t enter anything:

        public string GetInput(string prompt)
        {            
            while (true)
            {
                Output(prompt);
                string? answer = Console.ReadLine();
                if (!string.IsNullOrWhiteSpace(answer)) return answer;
            }
        }

We can now replace the direct references to Console with references to this:

string RunMethod(Func<string> readData)
{
    var io = new ConsoleInputOutputWrapper();
    int myNumber = Random.Shared.Next(100) + 1;

    io.Output("Guess the number that I'm thinking between 1 - 100");
    string? guess = readData();
    string result = BusinessLogic2(myNumber, guess);
    io.Output(result);
    return result;
}

We haven’t actually changed anything here, though – the console is still being written to. We need to be able to replace the functionality within the system for our test. We can do that by replacing the concrete class with an interface.

Adding an Interface

Adding an interface is much simpler than it may sound. Let’s see what needs to change in our ConsoleInputOutputWrapper class:

internal class ConsoleInputOutputWrapper : IInputOutputWrapper

We’ve implemented an interface that we’ve named IInputOutputWrapper – we’ve named it this because it’s more generic (that is, it doesn’t actually need to be a Console).

The interface just needs to specify the public methods in the class:

    internal interface IInputOutputWrapper
    {
        void Output(string text);
        string GetInput(string prompt);
    }

Whilst this syntax is specific to C#, the concept of an interface is not.

While we’re introducing an interface, and to clean our code a little, we can extract both our RunMethod and BusinessLogic methods into their own class – let’s call it Game:

    internal class Game
    {
        public string RunMethod(Func<string> readData)
        {
            var io = new ConsoleInputOutputWrapper();
            int myNumber = Random.Shared.Next(100) + 1;

            io.Output("Guess the number that I'm thinking between 1 - 100");
            string? guess = readData();
            string result = BusinessLogic(myNumber, guess);
            io.Output(result);
            return result;
        }

        public string BusinessLogic(int myNumber, string guessedNumber)
        {
            if (string.IsNullOrEmpty(guessedNumber))
            {
                return "Invalid guess";
            }

            if (int.Parse(guessedNumber) == myNumber)
            {
                return "Well done, you guessed!";
            }
            else
            {
                return $"Sorry, that was the wrong number, I was thinking of {myNumber}";
            }
        }

    }

This makes things much simpler. We can now create a constructor, and pass in our new interface:

    internal class Game
    {
        private readonly IInputOutputWrapper _inputOutputWrapper;

        public Game(IInputOutputWrapper inputOutputWrapper)
        {
            _inputOutputWrapper = inputOutputWrapper;
        }

Now that we have this instance, we can simply replace the method with a reference to this instead:

        public string RunMethod()
        {            
            int myNumber = Random.Shared.Next(100) + 1;
            
            string guess = _inputOutputWrapper.GetInput("Guess the number that I'm thinking between 1 - 100");
            string result = BusinessLogic(myNumber, guess);
            _inputOutputWrapper.Output(result);
            return result;
        }

We can now update our tests to call this new class, but we can pass in our own version of the IInputOutputWrapper, which may look like this:

    internal class MockInputOutputWrapper : IInputOutputWrapper
    {
        public string GetInput(string prompt)
        {
            return "5";
        }

        public void Output(string text) { }
    }

The test would then look something like this:

    for (int i = 1; i <= 100; i++)
    {
        // Arrange
        var inputOutputWrapper = new MockInputOutputWrapper();
        var sut = new Game(inputOutputWrapper);

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

        // Assert
        if (result == "Well done, you guessed!")
        {            
            return 0;
        }
    }
    return 1;

Next, we’ll skip number 3 and jump to 4.

4. The tests were not deterministic – they were dependent on the result of a pseudo random number

We can use the same pattern to create a wrapper for our random number chooser:

    internal class RandomNumberChooser : IRandomNumberChooser
    {
        public int Choose() =>
            Random.Shared.Next(100) + 1;        
    }

We can then mock that out, as before:

internal class MockRandomNumberChooser : IRandomNumberChooser
{
    public int Choose() => 12;
}

This definitely works, but it’s not brilliant. We have a few remaining issues – for example, if we want to test the number are the same, or different, we’ll need two mock classes. There are ways around this, too – for example:

    internal class MockInputOutputWrapper : IInputOutputWrapper
    {
        private readonly string _inputValue;

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

        public string GetInput(string prompt) => _inputValue;        

        public void Output(string text) { }
    }

We’ll come back to neater ways to achieve this in a future post, but for now, let’s put all this together and introduce a test framework.

Introducing a Test Framework

Test frameworks give you four basic things (some, in fact most, do more, but these are the absolute basics that you need – otherwise, you might as well roll your own):

1. A return value from the test run to determine whether the tests pass or fail
2. An ability to assert a value is in a given state
3. Some kind of integration into your IDE
4. Method discovery (that is, some way to mark your tests as tests)

For this example, we’ll use xUnit.net. Every language has its own options here – in .Net I’ve used MS Test, Nunit, and xUnit – and they’re all broadly the same; I’ve also seen libraries in Javascript and Python and, again, they mostly do the same stuff.

We’ll need to install the following libraries:

Install-Package Microsoft.Test.Sdk
install-package Xunit
Install-Package Xunit.Runner.Console
Install-Package Xunit.Runner.VisualStudio

This will enable you to create a test such as this:

[Fact]
public void RunMethod_GuessedCorrectly_CorrectTextReturned()
{
    // 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);
}

We no longer need to run this 100 times, because we can force a correct and incorrect guess:

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

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

            // Assert
            Assert.StartsWith("Sorry, that was the wrong number", result);
        }

Summary

We’ve now seen how we can manually mock functionality, and how that can help us to accurately test methods; we’ve also introduced a testing framework. In the next post, we’ll discuss mocking frameworks, and how they can make this even easier. We’ll also re-visit the test resilience.

Introduction to Unit Tests (with examples in .Net) – Part 1 – Structuring Tests

I’m intending this to be the first of a series on Unit Testing. In the series, I’ll discuss the basics of unit tests, the principles behind them, what makes a good unit test, what makes a bad unit test, and the technologies that you may choose to use to help you with them. I will not be covering test-driven development – this is simply about the mechanics and the reasons, not the methodology.

In this article, we’ll talk about what a unit test is, and how you might structure one. We will not be using any external tools for this, and what we do here should be possible in just about any language.

What is a Unit Test

A unit test is any way in which a single unit of functionality can be verified: it doesn’t have to be written before the code to be a test, it doesn’t have to be written in a test framework to be a test; it just has to run the code, and have some way of telling that the code has worked (the term “worked” is filled with ambiguity, but we’ll ignore that for the minute).

There are typically three parts to a unit test: they vary based on methodology, but essentially they are that you set-up the test, run the test, and check that the test worked; this is sometimes referred to as arrange, act, and assert.

For this section, we’ll be testing the following simple method:

int AddNumbers(int a, int b) => a + b;

Arrange

This is the part of the test where you configure the system under test (SUT). Given that you’re only testing a single piece of functionality, this can sometimes be quite involved, in order to get the system to place where it is ready to be tested, and actually running in a realistic manner. For our example above, this may look similar to the following:

// Arrange
int a = 4;
int b = 2;

Remember, we’re not using any external tools just yet – the above code could simply be in the Program.cs of a console application, or whatever the equivalent is in your language of choice; that is, just a simple program.

Act

The next part of the test actually exercises the code. The key thing here is that this is a unit test, so you would expect this to test a single unit of functionality; i.e., this should be a single line. In our case, it might look like this:

// Act
int result = AddNumbers(a, b);

We’ll come back to concepts such as mocking later in the series, but for now, let’s just agree with the comment that this part should exercise actual code; for example, there would be no advantage to the following code:

// Act
int result = a + b;

Your test may pass, but all you’re really testing is you compiler / interpreter. Writing tests that don’t actually test anything that you’re interested in is one of the biggest mistakes that I’ve seen with people new to unit testing. I would argue that having no tests at all is more valuable than a test that appears to provide coverage, but does not. After all, if there is no test, then you know that you need to create a test.

Assert

The final part of the test is to validate that the test passes – arguably this is around 50% of what you get from a testing tool like XUnit or JUnit – however, the following will work:

// Assert
System.Diagnostics.Debug.Assert(result == 6);

As in fact, will the more universal:

// Assert
if (result != 6) throw new Exception("Fail");

Unlike with the Act section, you can check several things are true; however, the test should be geared towards a single assertion. It’s worth bearing in mind that your assertion is that the functionality works correctly, not that a specific result is produced. This means that the test that we’ve discussed in this post is too specific.

Broadening a Test

Thinking about other possible scenarios, it’s tempting to introduce a randomised element into the test; that is, given two random numbers, the function will return the same result as that which the system independently calculates. I’m not saying this is a bad approach, but it isn’t a consistent one. This kind of test often leads to tests failing on some runs, and passing on others.

First Principles

I have no doubt that this has fallen out of favour somewhere, but the FIRST acronym provides some useful principles for testing:

Fast. Independent. Repeatable. Self-validating. Timely.

I won’t cover each one of these, but the essence of this principle is that when you run a test, you should have confidence that you can re-run the test with the same result (given the same inputs), and that your tests should be relevant to what you’re testing.

How to Broaden Our Test

Given our constraints, one easy way to broaden the test scope is to simply introduce multiple defined input parameters. In our case, perhaps instead of having two integers to feed in, we have an array and iterate through the array.

Naming a Test

The final thing that I want to cover in this first section is naming. There are many opinions on this, so there’s no right way; however, there probably are wrong ways. In general terms, the test should be named in a way that any person reading it could ascertain what is being tested; one popular version of this is to use the Given/When/Then form:

Given_TwoValidNumbers_When_AddNumbers_Then_CorrectResultIsReturned

Another one, that I personally use, is the format: Method Name/State Under Test/Expected Result; for example:

AddNumbers_TwoValidNumbers_CorrectResultIsReturned

The key here is consistency (i.e., don’t mix and match), and clarity; the following is an example of a bad test name:

AddNumbers_Works

In the next post in this series, we’ll talk about more complex tests, and mocking.

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

Integration Testing With In-Memory Entity Framework

As part of a project that I’m working on, I’ve been playing around with integration tests. In this post, I’m going to combine this previous post to cover a full end-to-end test that creates and tests an in-memory representation of the database.

As a quick caveat, there are some concerns over these type of in-memory database versions: for complex databases, that may well be true, but this is a very simple example. However, you may find that if you do try to apply this to something more complex that it doesn’t work as you’d expect.

Let’s start with setting up the WebApplicationFactory:

            var appFactory = new WebApplicationFactory<Program>()
                .WithWebHostBuilder(host =>
                {
                    host.ConfigureServices(services =>
                    {
                        var descriptor = services.SingleOrDefault(
                            d => d.ServiceType ==
                            typeof(DbContextOptions<MyDbContext>));

                        services.Remove(descriptor);

                        services.AddDbContext<MyDbContext>(options =>
                        {
                            options.UseInMemoryDatabase("InMemoryDB");
                        });
                    });
                });
            var httpClient = appFactory.CreateClient();

What we’re basically doing here is replacing the existing DB Context, with our in memory version. Next, we’ll prepare the payload:

            var myViewModel = new myViewModel()
            {
                MyValue = new Models.NewValue()
                {
                    Name = "test",
                    Uri = "www.test.com",
                    Description = "description"
                }
            };

            var json = JsonSerializer.Serialize(myViewModel);
            var content = new StringContent(
                json,
                System.Text.Encoding.UTF8,
                "application/json");

Finally, we can call the endpoint:

            // Act
            using var response = await httpClient.PostAsync(
                "/home/myendpoint", content);

In order to interrogate the context, we need to get the service scope:

            var scope = appFactory.Services.GetService<IServiceScopeFactory>()!.CreateScope();
            var dbContext = scope.ServiceProvider.GetService<MyDbContext>();

            Assert.NotNull(dbContext);
            Assert.Single(dbContext!.NewValues);

That should be all that you need. In addition to the caveats above, it’s not lightning fast either.

References

Integration Tests in Asp.Net

StackOverfow Question relating to adding DbContext to an integration test

Testing anAsp.Net web-app Using Integration Tests

Manually adding a DbContext for an integration test

Testing an Asp.Net Web App Using Integration Testing

I’ve recently been playing around with a tool called Scrutor. I’m using this in a project and it’s working really well; however, I came across an issue (not related to the tool per se). I had created an interface, but hadn’t yet written a class to implement it. Scrutor realised this was the case and started moaning at me. Obviously, I hadn’t written any unit tests around the non-existent class, but I did have a reasonably good test coverage for the rest of the project; however the project wouldn’t actually run.

To be clear, what I’m saying here is that, despite the test suite that I had running successfully, the program wouldn’t even start. This feels like a very askew state of affairs.

Some irrelevant background, I had a very strange issue with my Lenovo laptop, whereby, following a firmware update, the USB-C ports just stopped working – including to accept charge – so my laptop died. Sadly, I hadn’t followed good practice, with commits, and so part of my code was lost.

I’ve previously played around with the concept of integration tests in Asp.Net Core+, so I thought that’s probably what I needed here. There are a few articles and examples out there, but I couldn’t find anything that worked with Asp.Net 6 – so this is that.

In this post, we’ll walk through the steps necessary to add a basic test to your Asp.Net 6 web site. Note that this is not comprehensive – some dependencies will trip this up (e.g. database access); however, it’s a start. The important thing is that the test will fail where there are basic set-up and configuration issues with the web app.

The Test Project

The first step is to configure a test project. Obviously, your dependencies will vary based on what tools you decide to use, but the following will work for Xunit:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />		
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />

(See this post on Xunit libraries for details on the basic Xunit dependency list for .Net 6.)

The key here is to set-up the Web Application Factory:

var appFactory = new WebApplicationFactory<Program>();
var httpClient = appFactory.CreateClient();

We’ll come back to some specific issues with this exact code shortly, but basically, we’re setting up the in-memory test harness for the service (which in this case, is our web-app). You can obviously do this for an API in exactly the same manner. The rest of our test then looks like this:

using var response = await httpClient.GetAsync("/");

Assert.True(response.IsSuccessStatusCode);

If your test fails, and you want a fighting chance of working out why, you may wish to replace the assertion with this:

var content = await response.Content.ReadAsStringAsync();

That’s basically it; however, as that currently stands, you’ll start getting errors (some that you can see, and some that you cannot). It makes sense to make the HttpClient static, or at least raise it to the class level, as you only need to actually create it once.

Accessing the Main Project

The other issue that you’ll get here is that, because we’re using .Net 6 top level statements in Program.cs, it will tell you that it’s inaccessible. In fact, top level code does generate an implicit class, but it’s internal. This can be worked around my simply adding the following to the end of your Program.cs code:

public partial class Program { } // so you can reference it from tests

(See the references below for details of where this idea came from.)

Summary

In this post, we’ve seen how you can create an integration test that will assert that, at the very least, your web app runs. This method is much faster than constantly having to actually run your project. It obviously makes no assertions about how it runs, and whether what it’s doing is correct.

References

Example of testing top level statements

GitHub Issue reporting error with top level statements being tested

Stack Overflow question on how to access Program.cs from in program using top level statements

Tutorial video on integration tests