Nancy Testing – Razor View with Referenced Models

The last few weeks I’ve been working with Nancy (an awesome web framework for .Net), the core goal of the framework is the super-duper-happy path:

The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions.

This means that everything in Nancy is setup to have sensible defaults and conventions, instead of making you jump through hoops and go through configuration hell just to get up and running. With Nancy you can go from zero to website in a matter of minutes. Literally.

From the experience that I’ve had with Nancy to date, I would say it easily lives up to this goal for both development and testing. It is very easy to get started writing tests and most of what you need to know is covered in the docs.

However, on Friday I started experiencing a problem with some of our existing tests which check that the Razor view has been rendered correctly – by counting the number of rows in a <table>.

The cause of the failing test was that I changed the ViewModel to include a List of objects which live outside of the Web App assembly. To get my Nancy project to work when deployed I had to update the web.config file to include a list of assemblies for Nancy to reference when rendering the Razor views.

This morning I came back this problem afresh and found the solution 😀 Reading through the Razor View Engine docs on GitHub there is mention of the IRazorConfiguration:

You can specify assemblies and default namespaces that Razor needs to use whilst compiling the views by bootstrapping your own IRazorConfiguration implementation, thus removing the need to add the @using statements to each view. This step is totally optional if you don’t require additional references or namespaces in your view.

After trying various things I came across two different ways to get my tests to pass:

1. Update the App.Config file

This is the simple and easy solution, unfortunately I discovered this solution after the harder one below. On Friday I made the mistake of updating the web.config file which was in my Tests project and my tests kept failing – no surprise there.

What I should have done was update my App.Config file, after I did this all the tests passed.

Add the following section to the configSections group:

<section name="razor" type="Nancy.ViewEngines.Razor.RazorConfigurationSection, Nancy.ViewEngines.Razor" />

Then add the following to the end of the config file just before </configuration>:

<razor>
  <assemblies>
    <add assembly="Domain" />
    <add assembly="Some.OtherAssembly" />
  </assemblies>
</razor>

With that simple change my view tests passed. I guess the web.config file was added when I added the Nancy NuGet package.

2. Implement the IRazorConfiguration interface

The slightly harder solution is to implement the IRazorConfiguration interface and reference this when setting up the ConfigurableBootstrapper – the advantage of this is that you have finer controller over what is going on, the downside is that you will need to include this everywhere you are using the ConfigurableBootstrapper.

You will need to create a RazorConfigurationTestingStub which implements the IRazorConfiguration, mine looked like this:

internal class RazorConfigurationTestingStub : IRazorConfiguration
{

    public bool AutoIncludeModelNamespace
    {
        get { return true; }
    }

    public IEnumerable<string> GetAssemblyNames()
    {
        return new List<string>() { "Domain", "Some.OtherAssembly" };
    }

    public IEnumerable<string> GetDefaultNamespaces()
    {
        return Enumerable.Empty<string>();
    }
}

As you can see the list of Assembly names is the same list which was included in the App.Config file (in my Tests project) and the same list which is included in the web.config file (in my Nancy Web App project).

When setting up the ConfigurableBootstrapper you will need to include the stub as the implementation for the IRazorConfiguration dependency:

var bootstrapper = new ConfigurableBootstrapper(cfg =>
{
    cfg.ApplicationStartup((container, pipelines) =>
        {
            CookieBasedSessions.Enable(pipelines);
        });
    cfg.ViewFactory<TestingViewFactory>();
    cfg.RootPathProvider(new TestRootPathProvider());
    cfg.Module<Module.UnderTest>();
    cfg.Dependency<IThing>(thingInstance);
    <strong>cfg.Dependency<IRazorConfiguration>(new RazorConfigurationTestingStub());</strong>
});

After I did this all the tests passed.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s