Integration Testing in .NET Core 2.0
Tags: testing, beginners, programming, csharp
Published: 2017-08-31 03:52:32

---
title: Integration Testing in .NET Core 2.0
published: true
description: Learn how to create an in-memory integration testing framework that is quick and easy to setup for a .NET core 2.0 Web Service. 
tags: testing, beginners, programming, csharp
---


This post was first published on my [blog site](https://danieldonbavand.com/integration-testing/) 


We all know how important writing tests are when developing software, it ensures that your code is working as expected and allows you to more easily refactor existing code. Tests can also help someone new to your application learn how it works and what functions its offers. 

Each test level has its purpose, whether that be unit or integration testing. Having good integration tests are important when you are developing software. It ensures your application end to end flow is working correctly. 

While making sure your project has well designed integration tests, it is equally important that your tests are easy to run and fast. This is an important point, if there is a big investment to set up in order for the tests to run, or the tests take a long time to run, people are simply not going to use them.

This blog post shows you how to create an in-memory integration testing framework that is quick and easy to setup for a .NET core 2.0 Web Service.   

##In-Memory Testing
Using an in-memory web host allows us to setup and run our tests quickly and easily. Kestrel is a cross-platform development web server that is used by .NET core applications.


> Kestrel is a cross-platform web server for ASP.NET Core based on libuv, a cross-platform asynchronous I/O library. Kestrel is the web server that is included by default in ASP.NET Core project templates.
Kestrel supports the following features:
>
>* HTTPS
>* Opaque upgrade used to enable WebSockets
>* Unix sockets for high performance behind Nginx
>
>Kestrel is supported on all platforms and versions that .NET Core supports.


##Creating a simple .NET core 2.0 WebApi

Below I have setup a simple WebApi in .NET Core 2.0 with a single ping controller. This returns an OK response when called. I will create my integration test project inside this solution, then write and run my tests against the ping controller.

![2017-08-29_6-47-19](https://thepracticaldev.s3.amazonaws.com/i/d4f9b3fy7gcn3rcgah8m.png)


```
    public class HealthcheckController : Controller
    {
        [HttpGet]
        [Route("ping")]
        public IActionResult Ping()
        {
            return Ok();
        }
    }
 ```

##Setting up the Integration Test Framework

First let's create an integration test project inside our solution. I like to follow the following naming format `ProjectName.Integration.Tests`

Now we have our integration test project setup, we can start to create a test context, it is common for integration test classes to share setup and cleanup code we often call this a "test context". We will use the test context to setup a hosting framework ready to run our integration tests on. The test context for this example will be used to setup the test server and client.


![2017-08-29_6-47-20](https://thepracticaldev.s3.amazonaws.com/i/15lsxwe68om1strnmmq8.png)

We now need to install the following nuget package `Microsoft.AspNetCore.TestHost`

>ASP.NET Core includes a test host that can be added to integration test projects and used to host ASP.NET Core applications, serving test requests without the need for a real web host. 
>
>Once the Microsoft.AspNetCore.TestHost package is included in the project, you'll be able to create and configure a TestServer in your tests. 

Once we have install the TestHost nuget package, we need to setup the test server and client.

```
 public class TestContext
    {
        private TestServer _server;
        public HttpClient Client { get; private set; }

        public TestContext()
        {
            SetUpClient();
        }

        private void SetUpClient()
        {
            _server = new TestServer(new WebHostBuilder()
                .UseStartup<Startup>());

            Client = _server.CreateClient();
        }
    }
```

Before starting to write our actual tests, we need to install a few nuget packages. `xunit` and `xunit.runner.visualstudio` I also like to use FluentAssertions, if you are following along, then install the `fluentassertions` package as well. 

>Fluent Assertions is a set of .NET extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style test.

Another important package you need to install is the `Microsoft.NET.Test.Sdk` otherwise your tests will show "Test Inconclusive" in the ‘Test Session Runner’ when trying to run them.

Here is a list of the nuget packages and versions I have installed. I'm including this screenshot as often versions change and this can cause problems, also the error messages can sometimes not be very helpful. 

![2017-08-31_6-09-08](https://thepracticaldev.s3.amazonaws.com/i/bxuq8xnggycug7p85kjg.png)

The first test we are going to write is to test the ping controller. When we call the ping controller we should see an OK response. Very simple, but a good starting point to ensure your test framework and your WebApi are working correctly.

```
 public class PingTests
    {
        private readonly TestContext _sut;

        public PingTests()
        {
            _sut = new TestContext(); 
        }

        [Fact]
        public async Task PingReturnsOkResponse()
        {
            var response = await _sut.Client.GetAsync("/ping");

            response.EnsureSuccessStatusCode();

            response.StatusCode.Should().Be(HttpStatusCode.OK);
        }
    }   
 ```
 
That’s it, you now have an integration test framework, ready to add more tests to as you build out your WebApi. 
 
##Creating a Single Test Context
Creating tests with the structure above, creates a new test context per test scenario. This isn't always desirable, sometimes you want to setup your test context then run all tests or a collection of tests in your solution. 

Setting up your test context once can have massive benefits, for example, if you need to deploy and publish a database as part of your integration test setup, doing this is going to take some time to complete. It might not make sense to setup the database for each test scenario. What would be a better plan, would be to set it up once, then run all your tests that interact with the database.

Xunit allows us to setup and create collections.

First we need to create a collection class. This class can be named whatever make sense to you.

```
[CollectionDefinition("SystemCollection")]
    public class Collection : ICollectionFixture<TestContext>
    {
        
    }
```

The collection class will never have any code inside it. The purpose of this class is to apply the [CollectionDefinition] decorator and all of the ICollectionFixture<> interfaces. 

I have applied only one ICollectionFixture<TestContext>, but you can apply as many as you want. 

Next add the IDisposable interface to your TestContext class, to ensure context cleanup happens. 

```
  public class TestContext : IDisposable
    {
        private TestServer _server;
        public HttpClient Client { get; private set; }

        public TestContext()
        {
            SetUpClient();
        }

        private void SetUpClient()
        {
            _server = new TestServer(new WebHostBuilder()
                .UseStartup<Startup>());

            Client = _server.CreateClient();
        }

        public void Dispose()
        {
            _server?.Dispose();
            Client?.Dispose();
        }
    }
```

Now we add the CollectionDefinition name to the tests we want to run in a single collection 

```
    [Collection("SystemCollection")]
    public class PingTests
    {
```

If the test class needs access to the fixture instance, add it as a constructor argument, and it will be provided automatically.

```
  [Collection("SystemCollection")]
    public class PingTests
    {
        public readonly TestContext Context;

        public PingTests(TestContext context)
        {
            Context = context;
        }

        [Fact]
        public async Task PingReturnsOkResponse()
        {
            var response = await Context.Client.GetAsync("/ping");

            response.EnsureSuccessStatusCode();

            response.StatusCode.Should().Be(HttpStatusCode.OK);
        }
    }
 ```

An important note is that when running tests in a collection they do not run in parallel. If you want your tests to run in parallel, then you need to either split out the collections or not use collections at all. 

You can find the above code in my [GitHub repository](https://github.com/donbavand/dotnetcore-integration-tests-example)

Finally, if you want to discuss anything written here or in any of my other blog posts, you can find me on [Twitter](https://twitter.com/Donbavand)