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.

C#

1

2

install-package Nancy.Owin

install-package Microsoft.AspNet.WebApi.OwinSelfHost

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

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

publicclassTestController:ApiController

{

publicIEnumerable<string>Get()

{

returnnew[]{"hello","world"};

}

publicstringGet(intid)

{

return"hello world";

}

}

publicclassHelloModule:NancyModule

{

publicHelloModule()

{

Get["/"]=_=>"hello nancy";

}

}

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):

Owin Integration tests

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

C#

1

install-package Microsoft.Owin.Testing

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.

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

[TestFixture]

publicclassMyAppIntegrationTests

{

privateTestServer _server;

[TestFixtureSetUp]

publicvoidFixtureInit()

{

_server=TestServer.Create<Startup>();

}

[TestFixtureTearDown]

publicvoidFixtureDispose()

{

_server.Dispose();

}

[Test]

publicvoidWebApiGetAllTest()

{

varresponse=_server.HttpClient.GetAsync("/api/test").Result;

varresult=response.Content.ReadAsAsync<IEnumerable<string>>().Result;

Assert.AreEqual(2,result.Count());

Assert.AreEqual("hello",result.First());

Assert.AreEqual("world",result.Last());

}

[Test]

publicvoidWebApiGetTest()

{

varresponse=_server.HttpClient.GetAsync("/api/test/1").Result;

varresult=response.Content.ReadAsAsync<string>().Result;

Assert.AreEqual("hello world",result);

}

[Test]

publicvoidNancyGetHelloTest()

{

varresponse=_server.HttpClient.GetAsync("/").Result;

varresult=response.Content.ReadAsStringAsync().Result;

Assert.AreEqual("hello nancy",result);

}

}

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.

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

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

[Test]

publicvoidWebApiGetAllTest()

{

varclient=newHttpClient(_server.Handler)

{

BaseAddress=newUri("http://www.strathweb.com")

};

varresponse=client.GetAsync("/api/test").Result;

varresult=response.Content.ReadAsAsync<IEnumerable<string>>().Result;

Assert.AreEqual(2,result.Count());

Assert.AreEqual("hello",result.First());

Assert.AreEqual("world",result.Last());

}

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:

C#

1

2

3

4

using(varserver=TestServer.Create<Startup>())

{

//do stuff with server

}

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:

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.

Hi! Have you tried to run the Owin In-Memory with Ninject? I’ve a sample application here https://github.com/lcustodio/OwinNinjectWebApi. However I’m having a hard time to make it work, I’m getting a frequent 500 error, and the diagnostic tools are not helping much. Thanks for any hint.