DEV Community

Anton Ilin
Anton Ilin

Posted on

Testing of ASP.NET Core MVC apps using Microsoft Test Host

Automated testing is highly important. It helps not only to keep your code working after some changes but also makes easier the process of writing the code (TDD).

There are several approaches of testing ASP.NET Core MVC applications. The simplest one is just to create an instance of controller and call its methods in the test:

public class SomeControllerTests
{
    [Test]
    public async Task GetAll_ShouldReturnAll()
    {
        // Arrange
        var service = new SomeService();
        var controller = new SomeController(service);

        // Act
        var result = controller.GetAll();

        // Assert
        // TODO check result
    }
}
Enter fullscreen mode Exit fullscreen mode

But this approach has several problems:

  • You need to create controller with all dependencies
  • You don't test HTTP part (routing, status codes, serialization)

These problems could be solved using Microsoft.AspNetCore.TestHost nuget.

public class TestFixture
{
    public HttpClient HttpClient { get; private set; }

    public async Task Initialize()
    {
        var builder = new HostBuilder()
            .ConfigureWebHost(webHost =>
            {
                webHost.UseTestServer();
                webHost.UseStartup<Startup>();
                ConfigureWebHost(webHost);
            });

        _host = await builder.StartAsync();
        HttpClient = _host.GetTestClient();
    }

    private void ConfigureWebHost(IWebHostBuilder builder)
    {
        IConfigurationRoot configurationRoot = null;
        builder.ConfigureAppConfiguration((context, conf) =>
        {
            conf.AddJsonFile("appsettings.json");
            configurationRoot = conf.Build();
        });

        builder.ConfigureTestServices(services =>
        {
            // Here you can overwrite some services
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

You also need a small class which will help to serialize request models:

public class JsonContent : ByteArrayContent
{
    public JsonContent(object obj) : base(ConvertToBytes(obj))
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
    }

    private static byte[] ConvertToBytes(object obj)
    {
        var serialized = JsonConvert.SerializeObject(obj);
        return Encoding.UTF8.GetBytes(serialized);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you can create fake http host in your tests:

public class SomeControllersTests
{
    private TestFixture _sut;

    [SetUp]
    public async Task Setup()
    {
        _sut = new TestFixture();
        await _sut.Initialize();
    }

    [Test]
    public async Task GetAll_ShouldReturnAll()
    {
        // Act
        var request = new SomeRequest
        {
            // Some request data
        }

        var response = await _sut.HttpClient.PostAsync($"some-route", new JsonContent(request));

        // Assert
        // TODO check response
    }
}
Enter fullscreen mode Exit fullscreen mode

Also you can add required authorization by manipulating with HttpClient.

GLHF

Links

  1. https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-5.0

Top comments (0)