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.

blog comments powered by Disqus