OWIN/Katana in-memory integration testing - StrathWeb

Strath

December 30th, 2013

OWIN/Katana in-memory integration testing

Because in memory testing is extremely efficient!

A while ago we looked at testing the ASP.NET Web API pipeline using its in-memory hosting capabilities.

The advantages of such approach to end-to-end testing are unquestionable.

Now, with the emergence of OWIN as the primary hosting option for a wide array of web frameworks, it makes sense to explore how you could to the same, except in the OWIN (or rather Katana, since all the things shown here are Katana specific) context – so not just against Web API, but against any framework of your choice (running on top of OWIN & Katana).

Creating dummy app to test

Suppose you have a simple Owin app – in our case I’ll pull in Nancy and ASP.NET Web API and use them to create some testable endpoints.

We’ll need a dummy ApiController and a dummy NancyModule:

And, of course, this being an Owin/Katana app, let’s create a Startup class, where we configure the Web API routes and give it a priority over Nancy (the rationale is API routes should be more greedy):

Now we can proceed to writing integration tests for this.

Owin Integration tests

The easiest way to get started with OWIN integration tetsing is to install the Microsoft.Owin.Testing package from Nuget.

This will allow us to create an in-memory server, which will accept HTTP requests and issues HTTP responses without touching the network stack (entirely in process), which is both very efficient and extremely fast.

Note: if you do the tests in a different assembly from your web app (which I assume you do), and you use Web API or SignalR, you will need to add assembly binding redirects to your app.config). They are built with Microsoft.Owin 2.0.0 but the latest on Nuget is 2.0.2.

In these examples we will use nunit but of course any test framework of your preference is fine.

So what are we doing here? We spin up an instance of an in-memory test server per test fixture, and allow each test to use it to make HTTP calls through the OWIN pipeline. Then in the tear down, we get rid of it.

We can make calls to individual endpoints of our web application by simply using the HttpClient that hangs off the server, and consume it the same way as you would consume any HTTP service in .NET – and then perform the necessary asserts. By the way – the ReadAsAsync extension method comes from the Microsoft.AspNet.WebApi.Client Nuget package and is used here merely for deserialization convenience.

passedtests

If, for some reason, you don’t want to use the “built in” HttpClient property, you can instantiate your own HttpClient very easily:

In this case we create a test client with a dummy absolute BaseAddress (it’s mandatory) and pass in the HttpMessageHandler hanging off the TestServer to the client’s constructor. This syntax and approach to working with the client might be familiar to you, because that’s exactly how we worked with integration tetsing in the traditional ASP.NET Web API in-memory hosting.

Either way, initializing and working with the in memory server is extremely straight forward. You may prefer to isolate it entirely and initialize the test server in every unit test but as far as I am concerned, the per-fixture approach is fine too. In that case you would simply dispose it per test:

Interesting additional functionality is that you don’t even have to use your Startup class, as the entire config can be done inline using a lambda:

Have at it, my friends!

Be Sociable, Share!

  • Pingback: OWIN in-memory integration testing - StrathWeb ...

  • http://davepermen.net davepermen

    so the in-memory stuff isn’t really async, allowing you to access .Result directly, then? i was scared for the lack of await there for a moment..

    • http://www.strathweb.com/ Filip W

      well only the HTTP calls are blocking, nothing internally in the pipeline changes. if you use xUnit you can run the tests using async/await without any problems – in this case nunit can’t handle that

      • http://davepermen.net davepermen

        I missunderstood .Result. Didn’t knew it waits for the result. Just tested it out, and learned it. I always manually .Wait()ed before accessing it :)

        Everyday something new!

      • Standa K.

        NUnit handles async tests fine, I myself am using it.

  • Pingback: OWIN/Katana in-memory integration testing - Str...

  • Kieron Lanning

    Perfect timing, we’ve just implemented this at work!

    Did you have any issues setting the DefaultRequestHeaders on the TestServer’s HttpClient?

    Ours always comes out empty – ended up using a new HttpClient directly. Very strange.

  • Pingback: Andrey on .NET | Интересности #28

  • Martin

    How would you set up a fake database for your Api to use, using the WebApp.Start way?

    • http://www.strathweb.com/ Filip W

      Inject the DB into controllers using DependnecyResolver and then set up a fake dependency resolver in the tests against your HttpConfiguration.

  • dbtpictd

    I’m sorry for being naive, this claims this (what you’ve blogged) practice as unit testing, while your’s is integration testing. Does this entail, this practice is in one way ‘integration testing’ and in other way ‘unit testing’? Could you please clarify?

    • http://www.strathweb.com/ Filip W

      It’s integration testing since you run end to end requests, which go through your entire pipeline, consisting of different OWIN components and perhaps Web API artifacts too.

      Unit testing would mean testing individual pieces in isolation (i.e. just the controller, just the filter etc), which is definitely not the case here.

      • dbtpictd

        Thanks.