One of the nice things around the rising tide of OWIN in the .NET ecosystem is that it literally supports пїЅhosting anywhere пїЅ as long as thereпїЅs a viable host!пїЅ. For fans of TDD, the great thing about this is пїЅanywhereпїЅ includes пїЅinside your unit testsпїЅ.
This lets you build a really powerful development workflow where you can lean entirely on your test runner while building your APIs, and not have to bother with the painful cycle of breaking out into external tools. You get to execute the entire WebAPI stack, from inside your acceptance or unit tests and get rapid feedback.
This only works if youпїЅre using WebAPI hosted пїЅusing OWINпїЅ, and allows you to write tests that look like this:
Combined with manipulation of your container registrations, you can execute full stack tests with a single mocked out component like your data store like this:
Powerful right? Lets take a look at how we put this together over a vanilla WebAPI controller, with a single DIпїЅd dependency.
WeпїЅre going to use a few nuget packages пїЅ the ones provided by Microsoft to host OWIN components in IIS, some testing helpers that support in process hosting of OWIN components outside of IIS, and Ninject an IoC container.пїЅ We have a packages.json that looks like this:
Our solution looks like this:
There are a couple of important pieces here пїЅ the WebAPI app with itпїЅs OWIN Startup file, a Ninject dependency resolver to hook up IoC into WebAPI, and the controller described earlier. In addition to this we have the interface IGetValues implemented by ValueService. For this example, ValueService is very simple:
Your OWIN startup class is effectively your пїЅGlobal.asaxпїЅ пїЅ it bootstraps your app and configures components.
YouпїЅll see that weпїЅre configuring routes, creating a new Ninject пїЅStandardKernelпїЅ IoC container, and using the Ninject.Extensions.Conventions library to bind up all our components пїЅ in this case just our IGetValues service. IпїЅll skip over the implementation of the Ninject dependency resolver, but all it does is delegate calls to create components to the Ninject standard kernel.
Pressing F5 in Visual Studio will launch the WebAPI app in IIS Express, and you can visit it in a browser
Now we have a working WebAPI app, lets see how we can test it in memory. We want to build a test that runs the whole of the WebAPI stack in memory, and asserts on its response.
To do this, we need to use a couple of packages пїЅ the Microsoft Owin HttpListener package, the Owin Hosting package and Owin testing package, alongside our test framework (NUnit).
With those packages installed, we can write a test that wires all these components together.
What weпїЅre doing here is using the Owin hosting components to invoke our apps Startup class, hosted over HttpListener, on localhost on the port 8086. WeпїЅre then using a regular HTTP client to connect to this server, execute a request, and assert on a response. ItпїЅs a small marvel that we can do this at all, but TDDers will be cringing at the amount of noise in the test distracting you from the meaningful parts of your test пїЅ the preconditions and assertions. We can do better than this!
A Less Noisy Approach
Consider this class
Firstly, itпїЅs a base class that tidies all the noise out of the way пїЅ all the boilerplate code is moved into a test fixture setup and teardown, and weпїЅre detecting the first available free port to ensure that tests written execute on any machine theyпїЅre executed on. Using this class, our previous test becomes
instantly becoming readable and exposing only the things we really care about in the test пїЅ what weпїЅre asking our code to do, and what the response is. We can pretty much use this base class everywhere because itпїЅs bootstrapping our entire application for each text fixture.
Given how hard itпїЅs previously been to test the full ASP.NET web stack, this is a revelation пїЅ you can write full stack acceptance tests without an installed web server, and with no additional infrastructure or support.
In real world examples your application likely has many components that connect to and use external resources (databases, web services) that youпїЅll want to isolate and replace with test doubles. With some creative use of our IoC container, we can get the best of both worlds and execute full stack acceptance tests (because at this point, weпїЅre definitely not пїЅunit testingпїЅ) while swapping out пїЅjustпїЅ your data access component or пїЅjustпїЅ an API client library to provide fake responses.
To do this, we want to rebind parts of our application stack for each test, and luckily, Ninject (and pretty much any other good container) makes this quite easy. Consider the following additions to our base class
ItпїЅs a little bit long winded, but what weпїЅre doing is maintaining a dictionary of Mock objects (using Moq) and providing some helper methods for use in our unit tests. When a unit test calls the method пїЅMockOutпїЅ a mock is generated and returned for the test to use. This Mock is пїЅfrozenпїЅ for the duration of the test fixture and rebound into our IoC container.
What this means is that we can bootstrap our entire stack, and then re-register a single component to a Mock, letting us manipulate a single external resource. This becomes exceptionally useful in our broad acceptance tests
Here you can see weпїЅre replacing the implementation of IGetValues with a mock that returns a known value, and asserting that the full stack call returns a body with that value in it. The test is synthetic, but the application is very real пїЅ you could mock out API calls to third parties, mock out your entire data store or a single component and verify the full execution of your entire system.
These broad acceptance tests, combined with unit tests of individual components give you the perfect mix of high level пїЅfeature focusedпїЅ tests (you can add a BDD framework of choice if thatпїЅs your thing) that assert on behaviour not implementation and regular пїЅTDD Unit TestsпїЅ around the components that your system is composed from.
There are lots of parts of ASP.NET vNEXT that are пїЅcoming soonпїЅ or пїЅwait and seeпїЅ, but the community effort around OWIN and the maturation of some of the middleware frameworks makes this a technique you can and should adopt now.
This entry was posted on Wednesday, January 7th, 2015 at 5:09 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response. or trackback from your own site.
5 Responses to Testing an ASP.NET WebAPI app in memory
While not quite as completely end to end as the solution you have provided, you can also assign an HttpServer instance to be the HttpMessageHandler of an HttpClient, which allows you to use an HttpClient in exactly the manner you have described here, but without using any system resources to bind the site to an actual port (which has a happy side effect of not requiring you to run the tests as an administrator). Additionally, this lets you test sites which are not currently OWIN-hosted.
Really nice solution.
Question though. if your api uses the Authorize attributes how can we implement this with inmemory testing?
Hi. Have you ever had an issue where you ran a test suite and only the first test passes and the rest fail with test server returning 500 internal server error? How can I debug the 500 error?
if your api uses the Authorize attributes how can we implement this with inmemory testing.
If you need a mocking server, you can take a look at WireMock.Net. https://github.com/StefH/WireMock.Net
This is a C# .NET version which mimics the functionality from http://WireMock.org
Leave a Reply