
For quite some time I've been a fan and proponent of a .net web
framework called
Nancy. She
describe herself like a: "a lightweight, low-ceremony, framework for
building HTTP based services on .Net and Mono" and she looks like the
picture on the side.
There's much to admire about Nancy (a working web app in a tweet is
really cool) and the code and features are pure quality from start to
finish, much to the work that
@theCodeJunkie (Andreas
Håkansson) and
@grumpydev
(Steven Robbins) is putting in, with the help of a growing and engaged
community.
The thing that really blowed me away when I first saw it was the testing
abilities of Nancy. She's built for testing from the word Go and that
gives us some nice features to play with.
I thought I devote a couple of posts to the testing abilities of Nancy,
here's what I have planned:
1.
Intro to testing with Nancy(this post)
2.
The Configurable bootstrapper
3.
The Browser and Response objects
4.
Hat and shoeless testing with Simple.Data
5.
SpecFlow and Nancy
The underlying idea here is to get to know Nancy better, through tests.
Join me if you want. The speed of the blog posts will be much dependent
on how the book writing goes (Kanban In Action...). At the time of
writing I have the first two posts prepared, and the rest in my head.
### Why is Nancy easy.. to test
Nancy is a web framework built from the ground up. Which means that it
has no dependencies to System.Web or any of the web-stuff in .NET
framework. Those parts have been notoriously hard to test
(
mocking the complete Request-object is a nightmare
that still haunts many of us).
Not only that - the creators of Nancy have themselves worked with
testing as a main feature of the framework, probably even test-first.
This has led the framework to be very testable from the outset. To
connect back on my
post on constraints: they constrained themselves to
test everything, which made them create a very testable framework. Thank
you constraint!
There are two levels where this testability thoughts shine through to
great effect;
- Everything can be replaced! Nancy is built to replace every part of
her - even core properties such as the NancyEngine itself (you can
imagine what that does...). This is a dream for someone who needs to
mock stuff out.
- The [Nancy.Testing](http://nancy.testing/) framework helps you to
test the complete stack of an Nancy-application, without touching
slow and expensive resources such as the network.
That last part requires an explaination I think. When you create a
Nancy.Testing.Browser you need to pass in a
Nancy.Bootstrapper.INancyBootstrapper. That might be seen as cumbersome
but it gives you some great advantages and is not really hard as this
example will show you:
Moreover - this will actually test **everything**, the complete
Nancy-stack. Without hitting the network. Yes - I know. I didn't get
that first either. But let's look what possibilities that gives us first
and I'll try to explain it better afterwards:
As you can see from that example we can supply a fully populated
Request-object, with all the context we need for our Request (headers,
options, body you name it).
Executing that request (with the Get-method in this case to perform a
HTTP-GET returns a Response-object. That response contains the generated
view from the Nancy-module, meaning that it's been through the complete
Nancy-stack, except that it haven't gone through the network, hit any
web servers etc. And still you can access and search the generated view
with
CSS
Selectors as you would normally do in a web automation tool. It's
web automation with the web part ripped out - some people call this a
headless browser.
#### Contrasting with ASP.NET MVC options
If you were to test the same thing with an ASP.NET MVC application you
are faced with two options:
- test the controller directly. This is nice since the controller is
just a class. You can supply dependencies and control the way it's
called to test what you want. But you get back a View-object.
The templated view is not executed, so you don't know how the page
is generated.
- Which brings us to option number 2: test against the view. To do
this you will have to fire up a
browser automation tool that first need to
start. Then the application is "deployed" in your local IIS or
Casini web server. When that is booted up the first call to your
application is made, routed, the view generated and the HTML
returned.
In short - this takes a lot of time, and slows down both testing and
the feedback loop.
### Summing up Nancy testability
[Nancy.Testing](http://nancy.testing/) gives you a great way to test
your complete stack, with full control of it's execution. This in turn
gives you the opportunity to write small specific test, without a lot of
setup to get to the right page on the site etc, and a really fast
feedback-loop.
### The basic setup
Here follows the steps I went through to get started testing a new
application.
1. Created a new Solution,
NancyTesting
2. Added class library for test, DiscoverNancy.Tests
3. Nugot Nancy.Testing
(
Install-Package Nancy.Testing) into the test
class library.
4. Installed my test framework of choice: xUnit
(
Install-Package xUnit)
5. Wrote my first test
-
That failed of course since the application and route doesn’t
existed. But if failed with an error stating:
“Xunit.Sdk.EqualException: Assert.Equal() Failure
Expected: OK
Actual: NotFound”
-
So, the route was not found. I need to create the NancyModule that
holds it. That’s the famous Fit-In-A-Tweet-Module:
</div>
-
With that in place my test passed.
This was of course a very simplistic example, and I’ll be showing you
more advanced examples later. But it shows a lot of the testability of
Nancy already. For example, I have yet to move the SimpleModule into a
hosting environment and I can still test the whole stack…
The moving parts
In this post we have touched on all the parts of the
Nancy.Testing-framework, but very briefly. I thought I list the
important classes and concepts here and give a high-level description of
it:
- Nancy.Testing.Browser - this is the main object of the testing
infrastructure in Nancy. The class that you use to call your
application. It has methods for performing all HTTP Requests (GET,
POST, PUT … you know them) and returns a response object.
- The Request object is, as said above, our way to access the routes
and functionality in the Nancy Module under test. With the Request
object we can send in all the context (Forms, Querystring and
headers) that’s needed to test out our application.
- The Response object gives us the ability to assert the content of
our response, may it be simple status codes or complex views that’s
generated from our application.
- Bootstrapper - the
Bootstrapper is the thing that wires together a
Nancy application. From a testing point of view there’s great news
here. The bootstrapper is needed to create a Browser object and
through this we can control most of the environment, that the
NancyModule we are testing, is executing under.
Summary
In this first post of this series we took a quick look at the marvelous
testing capabilities of Nancy. We talked about why it’s so easy to test
and we briefly looked into the moving parts of Nancy testing.
In subsequent post we will dive deeper into these concepts and see how
we can bend them to our will, creating a excellent testing environment
for our applications.