Kevin Rohling

Building great s0ftware, 1 line at a time.

  Home  |   Contact  |   Syndication    |   Login
  8 Posts | 0 Stories | 41 Comments | 0 Trackbacks

News

Twitter












Archives

Service Locator: Integrating Unity and Mock Objects Testing in your Application
 Download Sample Code
Wanted to cover an issue I ran into in a couple of projects when using Unity for resolving my interface implementations and Mock Objects for testing. First, I’m assuming you have some idea of what Unity and Mock Objects are but for those who may be a bit fuzzy I’ll briefly explain:
Unity is a Dependency Injection and Inversion of Control Container, it’s very powerful and is capable of much more than what I’ll be describing here. However, for our purposes, it allows us to specify mappings in configuration between Interfaces and Implementations and at runtime ask for an instance of an Interface with no knowledge of the Implementation. This keeps our app very loosely coupled to those implementations.  This is extremely useful for Data Access Layers as we will see. Furthermore, I’d like to point out that this article is equally applicable to your DI or IOC container of choice, i.e. Spring J
Mock Object Frameworks  allow us to build “fake” objects for testing purposes that we can set up to behave similar to our “real” objects. This makes more sense within the context of a DAL: We can setup Mock objects to emulate a DAL but since there is no actual database behind them we are freed from the burdens of database Initialization (inserting supporting data) and Cleanup (removing the test data). Two of the more popular Mock Frameworks I’ve played with are Rhino Mock and Moq and I’m using Moq in this example.
Great, now we’re on the same page J Unity (and really IOC in general) is awesome for loosely coupling pieces of our application and Mock Objects are great for testing!
Question: Now what do these things have in common and why can it be difficult to use both of them in our application?
Answer:  Both of these frameworks play a similar role at runtime depending on whether we are testing or running our production code: 
·         In test we want to ask our Mock Framework for Mock implementations of our DAL interfaces. 
·         In production we want to ask Unity for real implementations of our DAL interfaces.
What makes this tricky is how we loosely couple our application to these frameworks so that we can swap them out under the covers.
This solution uses an IContractProvider interface, a static ContractManager class, and two implementations of IContractProviderUnityContractProvider and MockContractProvider:
 
   /* ContractFactory – Hides the details of ContractResolution from the rest of the application*/
    public static class ContractFactory
    {
        private static IContractProvider _contractProvider;
 
        private static IContractProvider ContractProvider
        {
            get
            {
                if (_contractProvider == null)
                {
                    //I want my default Contract Provider to by my Unity implementation
                    _contractProvider = new UnityContractProvider();
                }
 
                return ContractFactory._contractProvider;
            }
        }
 
        //Use this method to swap out my Contract Provider
        public static void SetContractProvider(IContractProvider contractProvider)
        {
            ContractFactory._contractProvider = contractProvider;
        }
 
        //Entry point for Contract Resolution for the rest of the application
        public static T ResolveContract<T>() where T:class
        {
            //Delegate this call to our Contract Provider
            return ContractFactory._contractProvider.ResolveContract<T>();
        }
 
    }
   /* IContractProvider – abstracts away Contract Resolution allowing different implementations */
    public interface IContractProvider
    {
        T ResolveContract<T>() where T : class;
    }
 
   /* Unity ContractProvider implementation*/
    public class UnityContractProvider : IContractProvider
    {
        private const string unitySectionName = "unity";
 
        private IUnityContainer _unityContainer;
 
        private IUnityContainer UnityContainer
        {
            get
            {
                if (this._unityContainer == null)
                {
                    this._unityContainer = new UnityContainer();
 
                    UnityConfigurationSection configurationSection =
                        ConfigurationManager.GetSection(unitySectionName) as UnityConfigurationSection;
 
                    configurationSection.Containers.Default.Configure(this._unityContainer);
                }
 
                return this._unityContainer;
            }
        }
 
        public T ResolveContract<T>() where T:class
        {
            return this.UnityContainer.Resolve<T>();
        }
    }
   /* Moq (Mock Object) ContractProvider implementation*/
    public class MockContractProvider : IContractProvider
    {
        //Use this to cache our Mock Objects so we have a singleton behavior
        private IDictionary<string, object> contractDictionary = new Dictionary<string, object>();
 
        internal Mock<T> GetMockObject<T>() where T:class
        {
            string contractName = typeof(T).AssemblyQualifiedName;
 
            if (!contractDictionary.ContainsKey(contractName))
            {
                Mock<T> mockObject = new Mock<T>();
                contractDictionary.Add(contractName, mockObject);
            }
 
            return contractDictionary[contractName] as Mock<T>;
        }
 
        #region IContractProvider Members
 
        public T ResolveContract<T>() where T: class
        {
            return GetMockObject<T>().Object;
        }
 
        #endregion
    }
 
I first encountered this issue in a project several months ago and have seen it come up in another one just recently where I’ve employed the same pattern. So far so good, the Unit Testers are happy and the Business Logic coders are none-the-wiser that anything has changed J
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Saturday, January 24, 2009 8:41 AM