Damian Hickey

Mostly software and .NET related. Mostly.

Testing Nancy with Owin.Testing

I always like a challenge :)

Nancy has a very nice way of testing, including a mechanism to configure the application as required for each test (swap in a mock etc). It does this with the Browser class:

[Fact]
public void NancyTest()
{
	// Arrange
	var browser = new Browser(with => with.Module<ConfigBootTestModule>());

	// Act
	BrowserResponse response = browser.Get("/config");

	// Assert
	Assert.Equal("Hello configured fellow", response.Body.AsString());
}

(The 'with => ' lambda here is altering the configurable boostrapper)

If you are hosting Nancy with OWIN, and you are using other middleware, you may prefer to test with Owin.Testing for broader test scope. I should state that Owin.Testing was indeed inspired by Nancy.Testing in the first place - I wanted to do the same type of testing with my OWIN application that was possible with Nancy.

So first let's create our OWIN startup class. Here, we are injecting the INancyBootstrapper which will allow us to supply a configurable one in a test:

private class Startup
{
	private readonly INancyBootstrapper _nancyBootstrapper;

	public Startup(INancyBootstrapper nancyBootstrapper)
	{
		_nancyBootstrapper = nancyBootstrapper;
	}

	public void Configuration(IAppBuilder builder)
	{
		builder.UseNancy(_nancyBootstrapper);
	}
}

We're going to add a helper method to configure the bootstraper, to make our test read more like the Nancy Browser example above:

private static HttpClient CreateHttpClient(Action<ConfigurableBootstrapper.ConfigurableBootstrapperConfigurator> configureBootstrapperAction)
{
	return OwinTestServer.Create(builder => 
		new Startup(new ConfigurableBootstrapper(configureBootstrapperAction)).Configuration(builder))
		.CreateHttpClient();
}

Here we are creating our test server, configuring the boostrapper via supplied action and returning an HttpClient.

And the Owin.Testing equivalent test:

public async Task OwinTest()
{
	// Arrange
	var httpClient = CreateHttpClient(with => with.Module<ConfigBootTestModule>());

	// Act
	var response = await httpClient.GetAsync("http://localhost/config");
	var body = await response.Content.ReadAsStringAsync();

	// Assert
	Assert.Equal("Hello configured fellow", body);
}

Looks familiar, doesn't it? ;)

Full gist.

Introducing Owin.Testing

Owin.Testing is discontinued. Use Microsoft.Owin.Testing instead.

Continuing in my mini-series of introductions, Owin.Testing (nuget, github) is an OSS helper library to host your OWIN application and, by using Owin.HttpMessageHandler, make in-memory testing of OWIN applications simple, fast, and environment dependency free. The method by which your application is invoked is using an HttpClient - a similar mechansim from which your users will be interacting with your application. Cookies support is supported by default (and can be turned off).

An example best demonstrates how this works:

//Arrange
OwinTestServer owinTestServer = OwinTestServer.Create(builder => new Startup().Configuration(builder));
HttpClient httpClient = owinTestServer.CreateHttpClient();

//Act
HttpResponseMessage response = await httpClient.GetAsync("http://localhost");

//Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
  1. Line #1 is how we create the test server. The Startup class is the class that defines your OWIN application.
  2. Line #2 is how we create the HttpClient that is internally configured to invoke your OWIN app's root application delegate.
  3. Line #3 & #4 is how we invoke and assert our application. (The assertion here uses the excellent FluentAssertions library).

And that's it! Fast, in-memory, CI friendly OWIN testing :)

A note on Owin.Testing history - I originally started this based of code from Gate. Later, Microsoft.Owin.Testing appeared which is similar, but has since been delisted. I have used some of the code from that. As far as I know at this point, there are no plans to revive Microsoft.Owin.Testing. So for the time being, I'll be continuing to maintain this.