.NET and me Coding dreams since 1998!

20Feb/085

Design for Testability – Castle Windsor (Part 5)

Pursuing the quest of Design for Testability, we've already covered:

(If you don't know what Dependency Injection (DI) Frameworks/IoC containers are, then I advise you to take a peek at Part 4 of this series first.)

The last episode covered the basic concepts of the DI frameworks, so today's post will present how those concepts are implemented in a DI framework named Castle Windsor.  Castle Windsor is the open source Inversion of Control (IoC) container piece of the Castle Project, which also contains ActiveRecord and MonoRail. There is only one installer for all three parts. Download it from the Castle project web site and install it to your GAC.
After installation, all you need to do to use Windsor is "Add reference..."  to: Castle.Windsor, Castle.Core and Castle.MicroKernel assemblies. 

Summary of the changes caused by Castle Windsor

Today's post will cover the same example I've used in previous DFT blog posts. This DI framework requires some changes to the code structure (although the functionality stays the same).

So, we are starting with this:

With this DI framework, we no longer need the internal properties, replacing them with Castle service locator calls. So the static diagram of the Castle solution looks like this:

image

(All of the types are contained in assembly "Windsor_Example.dll" and their name space is Example.Windsor. The solution also contains a Console application which makes a test call to the UserManager method.)

Summary: We have now three separate types withouth most of the DI plumbing code. Each type will locate the services it needs by using the built-in functionality of Castle Windsor DI framework.

Now, let's dive into the details of how this change is implemented ...

XML configuration

Windsor is a configuration-based DI framework, which means that the application's configuration file has to contain all the settings that the Windsor service locator requires.

Structure of a Windsor configuration file

The Windsor configuration information can be stored either in the default configuration files (App.config, web.config) or in it's own XML configuration file. In either case, it has to include:

  • the definition of the castle Windsor configuration section
  • Inside this section, a collection of components, each of which contains these three elements:
    • id (a key which can be used by the service locator to find an appropriate component to inject)
    • service (which describes the contracted behavior of the component - usually an interface)
    • type (which contains the component that implements the service contract - usually a class that implements the service interface)

The configuration file for our little example is contained in the App.config file of the console application. It looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="castle"
			type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
  </configSections>
  <castle>
    <components>
      <component id="userProviderService"
		service="Example.Windsor.IUserProvider, Windsor_Example"
		type="Example.Windsor.UserProvider, Windsor_Example"/>
      <component id="userManagerService"
		service="Example.Windsor.IUserManager, Windsor_Example"
		type="Example.Windsor.UserManager, Windsor_Example"/>
      <component id="companyManagerService"
        	type="Example.Windsor.CompanyManager, Windsor_Example"/>
    </components>
  </castle>
</configuration>

As you can see, I first define the castle configuration section and then, inside of that section, I have listed all the components contained inside the DI Framework container. The first two components are defined with service and type, while the third component (companyManagerService) is defined only by a type without a service (CompanyManager does not implement any interfaces). Both the type and service attributes contain fully qualified NET type names given in the format "namespace.type, assembly".

Reading the Windsor configuration file

If the Windsor configuration settings are defined in the default application configuration files, it can be accessed like this:

IWindsorContainer _container = new WindsorContainer(new XmlInterpreter());

We create a DI container by passing an instance of the XMLInterpreter to the Windsor container's constructor. This will enable the castle service locator to properly retrieve the desired type.

 

Alternatively, if we wanted to store our castle configuration settings in a separate configuration file (e.g. CastleConfig.xml), it can be accessed like this:

IWindsorContainer _container = new WindsorContainer(new XmlInterpreter("CastleConfig.xml"));

The only difference is that we have to provide a configuration file name to the XmlInterpreter constructor. The content of configuration file is the same regardless of where it is stored.

Different ways to locate a service

There are a few ways to locate a service. This example illustrates 3 of them (you can use intellisense to find others):

	IWindsorContainer _container = new WindsorContainer(new XmlInterpreter());

	IUserManager _userManager;
            
	//generic default service retrieval
	_userManager = _container.Resolve<IUserManager>();

	//service retreival only by given id
	_userManager = (IUserManager)_container.Resolve("userManagerService");

	// generic service retrieval for given id
	_userManager = _container.Resolve<IUserManager>("userManagerServiceA");
	_userManager = _container.Resolve<IUserManager>("userManagerServiceB");

In first example, I retrieve an instance of the user manager by calling the generic form of the container's Resolve method. If multiple components had the given service, the first one would be retrieved.

In the second example, the instance is located for a given id (note that it has to be cast).

In the third example, I retrieve a specific component. This is useful when you have multiple components that implement the same service. We could use this to implement the Strategy pattern.

Service Locator / Facade

From a performance perspective, it is critical that the container initialization occurs only once.

From architecture perspective, we would like to avoid having every solution dependent on Castle Windsor.

We can use the Facade design pattern to solve both problems.

 

This implementation uses a separate assembly which contains a singleton private container instance and some public methods (which delegate their calls to the appropriate container methods). The code looks like this:

using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

namespace Facade
{
    public static class ServiceLocator
    {
        private static IWindsorContainer _container 
            = new WindsorContainer(new XmlInterpreter());

        public static void Clear()
        {
            _container = new WindsorContainer();
        }

        public static T Resolve<T>()
        {
            return _container.Resolve<T>();
        }

        public static void AddInstance<T>(object instance)
        {
            _container.Kernel.AddComponentInstance<T>(typeof(T), instance);
        }
    }
}

So we see that ServiceLocator is a static class containing the singleton instance of the Windsor container in a private field. The container has been initialized to a set of types defined in a configuration file.

There are three public static methods exposed:

  • Clear - removes all the container components created from the configuration file (this will be used in tests)
  • Resolve<T> - retrieves the instance of desired container component
  • AddInstance<T> - adds a component based on the type instance to the container.

External usage of those methods doesn't require references to the Castle dlls and we get the performance of a singleton container.

Service location

Now that we have explained how service location works, let's take a look at how we would use the Facade ServiceLocator class.

using System;
using System.Collections.Generic;
using Facade;

namespace Example.Windsor
{
    public class UserManager : IUserManager
    {
        #region IUserManager Members

        public int NumberOfUsersActiveInLast10Days(string userName)
        {
            IUserProvider _userProvider = ServiceLocator.Resolve<IUserProvider>();

            IList userCollection = _userProvider.GetUserCollection(userName);
            int result = 0;
            foreach (User user in userCollection)
            {
                if (user.LastActivity > DateTime.Now.AddDays(-10))
                {
                    result++;
                }
            }
            return result;
        }

        #endregion
    }
}

If you compare this code with code presented previously in this blog series, you will notice that instead of injecting a dependency into the class through a constructor or setter property, we have now a self-contained method that does not depend on external variables. All this method does is call the "well-known" ServiceLocator type to resolve its dependencies. The rest of the code is exactly the same as in previous posts.

Writing unit tests using Castle Windsor DI framework

The only thing left is to write unit tests with mocks. The approach here is similar to standard mock testing:

  • create a mock instance using Rhino mocks
  • replace the real component with the mocked instance in the container
  • verify the expected behavior

So, if I would like to test the business logic in NumberOfUsersActiveInLast10Days, I would mock the UserProvider dependency (which is reading out the DB for values) and then just test the business logic there. That would look something like this (same test as in previous blog posts):

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers()
        {
            IUserProvider userProvider 
                =  mockRepository.DynamicMock();
            Expect.Call(userProvider.GetUserCollection(null))
                .IgnoreArguments()
                .Return(new List());
            
            //registering the mocked instance as container component 
            ServiceLocator.Clear();
            ServiceLocator.AddInstance(userProvider);

            mockRepository.ReplayAll();

            IUserManager _userManager = new UserManager();
            int count=_userManager.NumberOfUsersActiveInLast10Days("M");
            Assert.IsTrue(count == 0);
        }

 

Creating a mocked instance is pretty obvious. The new thing here is that I am calling the ServiceLocator.Clear method to get rid of the real user provider constructed in the container from configuration values. Once I have cleaned the container, I add the mocked instance. Now the container will return the mocked instance of IUserProvider to all the code asking for it. (The same thing could be done by using the AMC - Auto Mock Container, but I plan to dedicate a separate post on that subject, so I'll use the manual approach here.)

Once the container has been set up, the rest of the test is the same as when you use manual dependency injection.

What next?

The purpose of this blog post is not to go too deep into the details on Castle Windsor; it is more to give a concise overview of concrete steps for using this framework. For more information on Castle Windsor, I recommend these links:

Source code of the example presented in this post can be found here


Quote of the day:

When you encounter seemingly good advice that contradicts other seemingly good advice, ignore them both. - Al Franken

[edited by cbeauvais]

Comments (5) Trackbacks (0)
  1. I believe the first line of your NumberOfUsersActiveInLast10Days method should read:

    IUserProvider _userProvider = ServiceLocator.Resolve<IUserProvider>();

  2. Tim B,

    thanks for the tip… I corrected the typo (code sample was already containing the correct example)

    Thanks!

    Nikola

  3. I like the idea of having a Facade to the container which my component can reference instead of Windsor.

    However, I don’t like the idea of it being a static singleton.

    What I usually do is have this Facade as an interface, create the instance from my main() method, and add that instance to the container (to itself actually – a self containing container). This way, components who needs the container can use standard .ctor injection to obtain a reference to it. Easier to mock, no statics, and everyone’s happy :-)

  4. Omer,

    if I understand you well you are speaking something which sounds to me like you prefer to inject the container interface itself instead of using the ctor injection empowered by IoC to injecting the container components itself. I’ve seen quite a few opinions like that in ALT.NET mailing list and while I don;t have any strong argument against it my personal preference on this is that infrastructure shouldn’t leak to domain logic and Having ctor accepting IServiceLocator looks something like that. Another thing here (again IMHO) I don’t like is that it is variant of opaque DI (hides exact dependencies) which I would tackle in one of upcoming posts as something I dislike.

    On another note, why would you mock the ServiceLocator calls?  Isn’t easier just to use the SL in your test manually or through Auto Mocking Container and set the container components, run the test etc… I’ve never seen a test like that so if you could throw an example of how that test look like that would be really great

  5. Nice series on testability, dependency injection, and design patterns all in one.  The images (class diagrams and code snippets) are VERY useful.  Thank you


Leave a comment

No trackbacks yet.