The surprising ease of getting started with xUnit in .Net Core

As all developers are aware, learning a new programming language/library is something we do pretty much all the time. Sometimes it’s more challenging than others and in some circumstances, we may get frustrated and think “actually, I’m going to do this a different way”.

A complete opposite to this, for me, was xUnit. I was surprised as to how easy the library was to pick up and get going. xUnit’s own documentation is somewhat lacking, but this I can forgive due to the relative simplicity of getting started, most likely because their assumption is that users who will be writing in xUnit should already know .Net languages, in my case C#.

What’s good about it?

For a start, it’s very well integrated into Visual Studio 2017. Yes, most, if not all .Net Unit Test frameworks are supported by Visual Studio so I won’t give a +1 to xUnit specifically for this one but the Test Explorer in Visual Studio has made development, debugging and life-time running of Unit Tests an absolute breeze.

Another benefit is it’s natural adoption of general C# constructors and functions. There’s no need to create Initialisation functions so you essentially are writing normal .Net Core code, making it more maintainable and understandable for developers around you.

[Fact] and [Theory] are two attributes I really enjoy the naming scheme of. A small thing but they just make sense…
Fact, is literally “It takes this, so should return this”.
Theory is “It takes something like this and should output this”.

Subtle between the two but I have found the more I use xUnit with applications that use external data, the more I end up using [Theory] because of the ability to throw all sorts of data-sets at the function.

The challenges

With all new things comes challenges and xUnit does have them.

Entity Framework Contexts

The problem

One of the hardest things for me was getting Entity Framework Contexts to work correctly, with as little code as possible. Most of the code is already done in projects i want to test so the less code i have to duplicate or interface around is a necessity. There were some solutions online related to using Moq. For my situation, I did not feel the need when using Entity Framework, however as i progress and learn xUnit more, I may soon find my approach to be lacking what Moq could later provide.

The solution

The solution that I now use allows multiple In-Memory Database Contexts to be constructed with around five lines of code (excluding test data)

public class MockDbContext
{
    public DbContextOptions Options;
    public MyDbContext BuildContext(string functionName)
    {
        Options = new DbContextOptionsBuilder()
        .UseInMemoryDatabase(databaseName: functionName)
        .Options;
        MyDbContext context = new MyDbContext(Options);
        return context;
    }
}

I wouldn’t normally call database contexts “My” but in this example, it’s a very generic description.

This provides a generic function for a specific database context to be spun up by any test function with a unique database name. In my tests, this is essential so i can individually test each method with fresh data rather than having a single database with multiple database transactions moving about that could cause unexpected changes in the data that could corrupt my tests.

How would this be called?

As an example, one of the tests could look like the following:

public class MyTests
{
    private MockDbContext Mock = new MockDbContext();

    [Theory]
    [ClassData(typeof(DbCreateEntityRow))]
    public void EntityRowShouldAdd(List<newRow>)
    {
        // Arrange.
        Mock.BuildContext(nameof(EntityRowShouldAdd));
        using (MyDbContext temp = new MyDbContext(Mock.Options))
        {
            // Act.
            new MyDatabaseFunction(temp).AddRow(newRow);
            temp.SaveChanges();

            // Assert.
            Assert.True(temp.EntityRow.Where(a => a.RowId == 1).Any());
        }
    }
}

A simple example, but this concept can be applied to most, if not all database context testing situations.

  1. Make a reference to your MockDbContext class.
  2. Pull in the options that are publicly exposed.
  3. Spin up a temporary Database context to perform actions on.
  4. Check the action was successful.

There is a potential weak point with this method of creating a context; take note of the nameof() call that is sending the database name as that function name. Now, with [Theory] at the top of the function, I am saying that there could be more than one test data instance being passed to that function, so calling a database the same name could cause data conflicts in your Unit Tests so assess the need of your database name as and when you are writing tests.

Rewriting your brain for Unit Testing

The hardest challenge I found was rewriting the way I thought about code. When I write ASP.Net Core webpages, I tend to think “what should the server do here”, “what do I need to do to make this better” e.t.c. On the flip side, Unit Testing had me thinking more along the lines of “What can I do to make the server do, or not do what it should do”. Subtle difference, but it’s actually a lot harder to get your head around when you first glance. I therefore offer a few tips:

  • Don’t get bogged down in how the application works as a whole, focus on that one function you are testing. Think of that function as it’s own program and try and write functions around that single purpose.
  • Understand where Unit Testing sits in the application life-cycle. Instead of being deep in the specific function you are validating, it’s brushing the entry points of those functions, or think of it as a function call specifically, so therefore it has no true understanding of what is going on in the function, it just wants a black-box response.
  • You don’t need to test every function in your project! Test the most critical functions in your project and then work backwards until you get to a point where you are about to write a Unit Test for a function and say “This isn’t going to give me any benefit”. You’ve then tested your application to, in my opinion, the most optimal balance between maintainability and application reliability and longevity.

If you are also anything like me, you think of code visually so I offer this basic diagram to try and help show where you can make a Unit Test call sit in a virtual run-time situation.

UnitTestingGuide
Diagram explaining where Unit Testing calls could sit within an Applications Life-Time

Conclusion

Although a very quick run-down of my enjoyments and challenges of xUnit I hope this has helped smooth the pathway onto Unit Testing and xUnit. As I learn more and find more challenges or things I like, I’ll try and keep this post updated, or add another post on-top to further help people down the line.

My Adoption of jMeter

Introduction

As part of my work within the University, it has become necessary to build up Load Tests of business critical systems, so when releasing an upgrade to one of the systems, it is possible to identify our maximum possible load, whilst also seeing areas of improvements.

There were a number of possible Load Testing tools available, however the two most notable are

  • Visual Studio Web Performance Testing (VS-WPT) Tools
  • jMeter

These two attracted the most attention for a number of reasons.

  • Visual Studio is a hugely adopted IDE across enterprises and specifically within the University Establishment it is the main development tool for Web Applications.
  • jMeter was an existing load testing tool utilised by prior colleagues before my promotion to the post I am now situated in, although the load testing tool never really got it’s chance to shine due to configuration changes that left the existing load testing development redundant.
  • Both tools can be incorporated within Visual Studio Team Services (VSTS) and run via Azure.

Initially, VS-WPT was used as this is the easiest tool to pick up and start using, the difficulty with this tool became apparent soon after trying to development tests past login screens. Documentation and user adoption was lacking for this tool at the time of writing and made it extremely difficult to progress.

Once the frustration set in, I turned my attention to jMeter to try and combat this issue, as I had been informed of prior success with the tool. After a few hours of patience and YouTube videos, the understanding of jMeters power begun to set in. It’s simplicity started to come to light, minus a few frustrations with the tool.

File and Folder Structure

During development of load tests it became apparent of the ever growing need for some form of configuration that would allow for reuse of load test functions across all load tests, most notably the login function.

I chose to use my understanding of the MVC framework and structured my folders in a manor that allowed reusable functions to be stored and controlled much easier. An important thing to mention is the adoption of MVC was around the API version of MVC where the View (V) section isn’t really required, essentially forming a MC framework.

Each load test project would use two main folders:

  • Modules (M)
  • Load Tests (C)

The Modules folder is designed for the reusable files, where they can all be stored and called as necessary. In the future, this folder may need folders within it, to facilitate more file clarity, but at the time of writing, the folder structure is perfect for its requirements.
The Load Tests folder is designed to house the load tests that have been developed. Providing a one-stop-shop for load tests related to a specific service.

Ease of Environment Variables

jMeter surprised me from the first time I used it’s “Include Modules” functionality where I was able to call jMeter files from around my pc. When calling these files during runtime, jMeter automatically adds the file to scope of the parent file and allows the child files to use Variables defined in the parent layer without the need to pass any variables in a command line or function call. That being said, I’m sure a number of people would find this worrying however on an implementation level, it is also possible to have local variable definition should the need suit you.

My main issue with jMeter

Why can’t I create dynamic file paths in the “Include Modules” function? It would make scalability a lot better as the need to rename each functions folder structure will be much easier when it occurs due to changing potentially one variable which would span across all “Include Modules”.

Conclusion

jMeter as a tool is fantastic for very in-depth load testing, whilst at the same time giving a level of simplicity that you aren’t grinding your teeth at the sight of a bug in your development. I will be continuing to use the tool and hope to develop a suite of resources within the department I work for to provide an easy adoption of load testing.