Test,  Unit test

HOW TO CREATE A TEST FIXTURE

A test fixture is used to:
Make the code less brittle. We isolate the construction from all the tests and only do it in one place, so when we add a new parameter in the future, we only have to change the test code in one place.
Makes the job of writing tests easier, we write less code because we only call a function that creates the instance, instead of writing the entire construction with all the parameters in every test.
Make the code DRY (Don’t Repeat Yourself). We only do the construction, the newing up, in one place.

The code

internal class ClassUnderTestFixture
{
    public Mock<IInjectedClass> InjectedClass { get; set; } = new Mock<IInjectedClass>();

    public ClassUnderTest CreateSut()
    {
        return new ClassUnderTest( InjectedClass.Object);
    }
}

Moq is used in this example. Obviously, there’s nothing stopping us from using any other mocking framework you like. I just had to settle on something.

The explanation

The class has two major features:

  • A property for each parameter in the constructor of the SUT (What is a System Under Test? Read about it here). To create the SUT we have to provide it with all the in-parameters that it requires. We do this by giving it a mock of each.
  • A function called CreateSut()
    This is used in the tests every time we need to create an object of the class we’re testing.
    It creates the SUT, using the properties as parameters.

The properties

Why do we even bother to create a full blown public property for each in-parameter? Why not just put the mock directly in the constructor? Like this:

public BadWayToInjectClassFixture CreateSut()
{
    return new BadWayToInjectClass ( new Mock<IInjectedClass>());  // <== Mock here without property.
}

Well, we certainly could. But we would make the fixture a little bit less flexible. It happens, admittedly not often, but still, that we need to provide our own version to the constructor. For instance, we might want to inject the actual code and not a mock. So, to not limit our options, we make each parameter as a property.

But wait, doesn’t that mean a lot of extra coding? Well, yes, but if we use snippets and templates, we make the computer do the coding for us. Really, do check that out if you are a lazy developer!

On the other hand, if we always write it like this, and only add properties as we need them, well, that will definitely work too. Actually, it is a little bit more YAGNI (You Ain’t Gonna Need It).

The function called CreateSut()

In a fixture, we need a place where we new up the class that we are testing. And this is it! This is the function we call every time we need a new instance of the class. Its only purpose is to new up the class under test with all the necessary in-parameters.

I have chosen the name CreateSut(), because it creates the SUT, the System Under Test, i.e. the class that we are testing. I think that it describes the intention of the function quite well. Obviously, you can choose any name you like.

Naming the class

I use a simple naming scheme. I combine the name of the class that the fixture creates with the word “fixture”. The intention of the class is dead clear. It is a test fixture for the class which name is in front of the word fixture. Self-documenting code, I guess. Look at this example:

class Repository  // The class we’re testing.
class RepositoryTests  // The class that is testing it.
class RepositoryFixture  // The class that is creating it.

We clearly see that they belong together. And they say that naming classes is hard…

How to use the fixture

Here is an example of how to use the fixture.

[TestClass]
public class MyClassTests
{
    private MyClassFixture _fixture;

    [TestInitialize]
    public void Setup()
    {
        _fixture = new MyClassFixture();
    }

    [TestMethod]
    public void MyMethod_DoesThis()
    {
        // Arrange
        var sut = _fixture.CreateSut();

        // Act
        var result = sut.MyMethod();

        // Assert
        result.Should().Be(true);
    }
}

The fixture is a member variable in the class. It is initialized every time a test is executed. The only reason for this, as usual in unit tests, is to clear any residue from previous tests to avoid unpredictable results in any of the other tests.

And as we see under the Arrange section in the test, we call the CreateSut() function to generate a new instance of the class we’re testing.

Internal, not public

The fixture is only intended to be used with the tests. This means that it never will be used outside the test assembly. So why even expose it to other assemblies in the first place? Make it an internal class and let the computer enforce the architecture, and make sure it never gets exposed, so we don’t have to think about it at all.

But why should I use a test fixture?

A test fixture is a way to make it faster and easier for we to write our tests. And it makes our tests less brittle when the code changes in the future. Not to mention that we make it DRY, which always is a good practice.

Speed

If we don’t use a test fixture, then we have to create the SUT in every test we write. And since we use Dependency Injection, we often have a lot of parameters in the constructors. And we have to code them, by hand, every time we create a new test.

Now, we just write myFixture.CreateSut(), and we are done.

Less brittle

Consider this scenario. We’re all done, all tests are written, and the code has been in production for a while. Then a new user story shows up and we have to add a new dependency to our class. We put it in and make the code work.

Except that when we build, we get 40 tests that fail. Yes, we forgot that we also new up the class in each of them. And now we have to add that new parameter in each and every one of them.

Now, let’s say that we used a fixture instead. We only have two places to change. The production code and the fixture. We have effectively isolated all our tests from the hassle of newing up classes and future changes to the class.

DRY, Don’t Repeat Yourself

And we can bask in the respect of our co-workers when we state that we are persons that know what DRY code and good architecture is.

— Cheers

Like it? Share it!

Leave a Reply

Your email address will not be published. Required fields are marked *