Improving testability with the Castle Dictionary Adapter

Frequently when reviewing code I see one of my pet hates appear and that’s a direct dependency on the ConfigurationManager.  The ConfigurationManager provides a way to access values in the Web\App.config. Yet, like any dependency, they generally bite you at some point – generally when you attempt to write the test.

Let’s imagine that our web.config has a value like below:

EnableNewsletterSignup = “false”

This value defines if we should hit the live web service. During development\systest we don’t want this to happen, however we do in UAT and Live. As a result, our code will generally look like this:

public bool Signup(string email)
{
    if (!Boolean.Parse(ConfigurationManager.AppSettings["EnableNewsletterSignup"]))
        return false;

    return true; // technically this would go off to an external web service
}

Simple, yet with multiple problems

Firstly, we have a magic string value which relates to the key in the config. If we wanted to change this value we would have to perform an error-prone Search\Replace. Secondly, we have to manually parse the string value to a boolean – again, this is error prone as we’ll need to protect against bad data. This additional logic hides the true intent of what the method is meant to be doing which increases complexity. To make matters worse, we have a major problem when it comes to testability.

The configuration manager will automatically detect the config file based on the executing assembly, this means that your test assembly’s App.config needs to match your implementation’s (web.)config with all the values pre-configured for testing purposes. Having pre-configured values offers you very limited flexibility and in the example above we would be unable to test both paths (without our tests changing the value directly)? If we had multiple possible paths, this would cause us a very real problem.

This week I came across the issue were I required an AppSetting value. Not wanting to face the issues above I looked for help.

Thankfully, help’s available

The Castle Dictionary Adapter removes these problem for us. Given an interface and a dictionary of values, the adapter will create an object with all the properties populated for us. Our interface will match the settings in our config file.

public interface IApplicationConfiguration
{
    bool EnableNewsletterSignup { get; set; }
}

The same implementation mentioned before becomes this, with a dependency on the above interface instead of the concrete ConfigurationManager. Notice our ‘if’ statement now uses a strongly typed property without all the noise associated.

class NewsletterSignupService
{
    private readonly IApplicationConfiguration _configuration;

    public NewsletterSignupService(IApplicationConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool Signup(string email)
    {
        if (!_configuration.EnableNewsletterSignup)
            return false;

        return true; // technically this would go off to an external web service
    }
}

Testing!

The real advantage arrives when you look at the problem from the testing point of view. Because it’s an interface, we can use Rhino.Mocks to produce a stub, allowing us to test using any possible value.

var stubConfig = MockRepository.GenerateStub<IApplicationConfiguration>();
stubConfig.EnableNewsletterSignup = true;

We also no-longer need to maintain the App.Config as everything is driven by stub config objects, making life easier all round.

The next level comes when you use it with an IoC framework such as Castle Windsor. When an object defines a dependency on IApplicationConfiguration, they will be provided with an object created via the DictionaryAdapterFactory with the values coming from our actual AppSettings.

WindsorContainer container = new WindsorContainer();
container.AddFacility<Castle.Facilities.FactorySupport.FactorySupportFacility>();

container.Register(
    Component.For<IApplicationConfiguration>().UsingFactoryMethod(
        () => new DictionaryAdapterFactory()
             .GetAdapter<IApplicationConfiguration>(ConfigurationManager.AppSettings)));

As a result of implementing the adapter together with it’s use in Windsor we have more control, less complexity and a more maintainable solution going forward.

But it’s not only for AppSettings, the Castle Dictionary Adapter works on a number of different directories and collections meaning you no longer need to index into them using strings. If you want to know more, then CastleCasts has a great screencast on this at http://castlecasts.com/Episodes/3/Show/dictionary-adapter

In order to implement this in your own codebase, Castle Dictionary Adapter is currently a separate single assembly with no external dependencies that you can download from http://www.castleproject.org/castle/download.html

Going forward, it will be part of Castle Windsor 2.5 with some interesting improvement as discussed at http://devlicio.us/blogs/krzysztof_kozmic/archive/2010/07/05/castle-windsor-2-5-the-final-countdown-beta-1-released-and-core-dynamicproxy-dicitionary-adapter.aspx

 

The code for the above example is available at http://gist.github.com/486603

 

About benhall

Ben Hall is a UK C# developer\tester with a strong passion for software development and loves writing code. Ben enjoys exploring different ways of testing software, including both manual and automated testing, focusing on the best ways to test different types of applications. He also loves developing web applications using ASP.net and Ruby on Rails. Ben is an ASP.net MVP and can be contacted by emailing Blog {at} Ben Hall .me .uk
This entry was posted in Castle, TDD, Testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Dinesh Manne

    I have been doing something similar with the NameValueDeserializer from the MvcContrib project

  • Leon Breedt

    Agree.

    If you’re using a strongly typed language, make the types work for you, don’t make it a stringly typed language.

  • http://www.sharpbites.com alberto

    Awesome post! Depending on the config file is always a nightmare, and not having to manually create config classes is a bless. Thanks.