In Process Http Server for Integration Test Faking with Owin, Katana, and WebAPI

Sometimes when integration testing we need an HTTP endpoint. We can set one up in our solution (for example a Web Api project) and make sure it’s running before we execute our integration tests but it can be painful. Also consider when running on a build server, the web site will need to be provisioned, etc.

For isolated integration tests that require some HTTP endpoint we can create an HTTP endpoint from within our test code that doesn’t require a separate web project. This means that when tests run they have no external dependency in the sense of a “real” website being hosted somewhere – even if that somewhere is on the local dev machine. Another advantage of the approach outlined below is that because it’s all in-process it’s also faster than actually going through the network stack.

The System Under Test

We are going to test the following class that calls a service to change a string to uppercase:

using System;
using System.Net;

namespace ClassLibrary
{
    public class ToUpperServiceGateway
    {
        private readonly string _serviceEndpoint;

        public ToUpperServiceGateway(string serviceEndpoint)
        {
            _serviceEndpoint = serviceEndpoint;
        }

        public string MakeUppercase(string lowercase)
        {
            using (var wc = new WebClient())
            {
                return wc.DownloadString(_serviceEndpoint + "/" + lowercase);
            }
        }
    }
}

This code uses WebClient to call a web service. In the integration tests we want to spin up a website that will return a mock value for example.

Writing the Initial Test Code

So an initial test could look somethine like:

using Xunit;

namespace ClassLibrary.IntegrationTests
{
    public class UpperCaseTests
    {
        [Fact]
        public void ShouldGetUppercase()
        {
            var sut = new ToUpperServiceGateway("http://localhost:8084/api/toupper");

            var upper = sut.MakeUppercase("hello");

            Assert.Equal("HELLO", upper);            
        }
    }
}

If we run this we get “System.Net.WebException Unable to connect to the remote server” as we’d expect as there’s no website at the address.

Creating an In-Process Web API Endpoint

First off, in the test project install a few of NuGets: Microsoft.AspNet.WebApi.OwinSelfHost and Microsoft.Owin.Testing.

The first thing is to create a Web API controller, again in the test project, to fake out a real service:

using System.Web.Http;

namespace ClassLibrary.IntegrationTests
{
    public class ToUpperController : ApiController
    {
        public string Get(string lower)
        {            
            return "FAKE"; // fake value
        }
    }
}

Here, regardless of what’s passed in we’re just returning a fake value.

The next task is to create some configuration for Owin setting up our test controller:

using System.Web.Http;
using Owin;

namespace ClassLibrary.IntegrationTests
{
    public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            var config = new HttpConfiguration();

            config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{lower}");

            appBuilder.UseWebApi(config);
        }
    }
}

We can now refactor the test to create an in-memory Web API controller that can respond to our SUT:

using Microsoft.Owin.Hosting;
using Xunit;

namespace ClassLibrary.IntegrationTests
{
    public class UpperCaseTests
    {
        [Fact]
        public void ShouldGetUppercase()
        {
            using (WebApp.Start<Startup>("http://localhost:8084")) // base hosting address
            {
                var sut = new ToUpperServiceGateway("http://localhost:8084/api/toupper"); 
                // api/toupper matches our test controller / route

                var result = sut.MakeUppercase("hello");

                Assert.Equal("\"FAKE\"", result); // extra " because Web API response is not returning text/plain
            }
        }
    }
}

The test now passes, as our SUT connects to our in-memory test controller.

Note: For even simpler code that doesn’t require a test controller we could also use Nancy.

SHARE:

Comments (1) -

  • Togakangaroo

    6/21/2014 1:54:24 AM | Reply

    I've done this before. After setting it up though Web Api ends up being overkill. Just start Owin SelfHost create an OWIN middleware that returns exactly what you want it to return. Watch out for this by the way http://stackoverflow.com/q/22671502/5056

Pingbacks and trackbacks (1)+

Add comment

Loading