Mocking objects inside an IOC container

In: C#|Inversion Of Control|Unit Testing

9 Jul 2010

Every now and again it’s necessary to resolve a dependency at runtime. When this happens you don’t really have much of a choice but to insert mock objects into your test fixtures IoC container. The following patterns allow me to specify 1 abstract base class and have all dependent unit tests inherit these stubs thus satisfying their dependencies.

An example class that uses a service locator pattern. Note: This will also work for constructor based dependency injection as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class CustomerLeaseTerm
{
    public virtual Lease Lease { get; set; }
    public virtual Invoice Invoice { get; set; }
    public virtual long AdditionalDataTransfer  { get; set; }
 
    // Lazy Load the Additional Data Transfer Broker using the Service Locator Pattern
    private IAdditionalDataTransferBroker _additionalDataTransferBroker = null;
    public virtual IAdditionalDataTransferBroker AdditionalDataTransferBroker
    {
        get { 
            return _additionalDataTransferBroker 
                ?? (_additionalDataTransferBroker = IoC.Resolve<IAdditionalDataTransferBroker>()); 
         }
    }
 
    // Return a calculated cost at runtime using the Additional Data Transfer Broker
    public virtual decimal AdditionalDataTransferCost { 
      get 
      {
          return AdditionalDataTransferBroker
                   .GetByUnitsInGigabytes(AdditionalDataTransfer)
                   .EffectiveCost;
      }
    }  
 
   (...)
 
}

So, how do we add mock objects into an IoC Container?

Because we have a class which has a dependency on a windsor container using IoC.Resolve(), we could satisfy our IoC dependencies in two ways.

1. By adding the mocked instance to the IoC Container.

container.Kernel.AddComponentInstance<ITYpe>(myMockedObject);

2. By mocking the container itself using Rhino and then stubbing the Ioc.Resolve method to return our mocked object (preferred).

container.Resolve<IType>();

I prefer to add the container initialization into an abstract base class, this allows multiple unit test fixtures to inherit a stubbed version of all of the IoC dependencies. In addition to that I can simply modify 1 test fixture to override InitializeStubs() to allow me to specify my mocked data for testing.

By adding these to an abstract base class this also allows me to satisfy most of Uncle Bobs SOLID priciples of OOD. See http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod for a full disclosure of who Uncle Bob is and what is SOLID.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/// <summary>
/// An Abstract Base Class containing common Service Locator Objects required to be resolved from an IoC Container during runtime.
/// Override InitializeStub to change the default behavior of the common objects.
/// </summary>
public abstract class IocFixtureBaseClass : FixtureBaseClass
{
	protected IAdditionalDataTransferBroker AdditionalDataTransferBroker;
	protected IAdditionalMemoryBroker AdditionalMemoryBroker;
	protected IAdditionalStorageBroker AdditionalStorageBroker;
	protected IWindsorContainer Container;
 
	public override void SetUp()
	{
		base.SetUp();
		InitializeIoC();
	}
 
	protected virtual void InitializeIoC()
	{
		AdditionalStorageBroker = MockRepository.GenerateStub<IAdditionalStorageBroker>();
		AdditionalMemoryBroker = MockRepository.GenerateStub<IAdditionalMemoryBroker>();
		AdditionalDataTransferBroker = MockRepository.GenerateStub<IAdditionalDataTransferBroker>();
 
		Container = MockRepository.GenerateMock<IWindsorContainer>();
 
		Container.Stub(x => x.Resolve<IAdditionalStorageBroker>()).Return(AdditionalStorageBroker);
		Container.Stub(x => x.Resolve<IAdditionalMemoryBroker>()).Return(AdditionalMemoryBroker);
		Container.Stub(x => x.Resolve<IAdditionalDataTransferBroker>()).Return(AdditionalDataTransferBroker);
 
		InitializeStubs();
 
		IoC.Initialize(Container);
	}
 
	protected virtual void InitializeStubs()
	{
		var mockAdditionalMemory = new AdditionalMemory();
		var mockAdditionalStorage = new AdditionalStorage();
		var mockAdditionalData = new AdditionalDataTransfer();
 
 
		AdditionalMemoryBroker.Stub(x => x.GetById(0)).IgnoreArguments().Return(mockAdditionalMemory);
		AdditionalStorageBroker.Stub(x => x.GetById(0)).IgnoreArguments().Return(mockAdditionalStorage);
		AdditionalDataTransferBroker.Stub(x => x..GetById(0)).IgnoreArguments().Return(mockAdditionalData);			
	}
}

An example test fixture would go something like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[TestFixture]
public class LeaseFixture : IocFixtureBaseClass
{
    private IExcessDataUsageCostService _costService;
 
    public override void SetUp()
    {
        base.SetUp();
         _costService = new ExcessDataUsageCostService();
     }
 
    public override void InitializeStubs()
    {
        var mockAdditionalMemory = new AdditionalMemory() { id = 1, CostInCents = 500, UnitsInMegabytes = 128, Text = "Mocked Memory" };
	var mockAdditionalStorage = new AdditionalStorage() { id = 1, CostInCents = 1000, UnitsInMegabytes = 5000, Text = "Mocked Storage"};
	var mockAdditionalData = new AdditionalDataTransfer(){ id = 1, CostInCents = 1000, UnitsInMegabytes = 5000, Text = "Mocked Data"};
 
 
	AdditionalMemoryBroker.Stub(x => x.GetByUnitsInMegabytes(128)).Return(mockAdditionalMemory);
	AdditionalStorageBroker.Stub(x => x.GetByUnitsInGigabytes(5)).Return(mockAdditionalStorage);
	AdditionalDataTransferBroker.Stub(x => x.GetByUnitsInGigabytes(5)).Return(mockAdditionalData);	
 
    }
 
   [Test]
   public void GetByIdReturnsAnObject()
   {
         var customerLease = new customerLease();
          customerLease.CustomerLeaseTerm.AdditionalDataTransfer = 5; 
 
          // AdditionalDataTransferCost is a calculated field at runtime based on a value per Gigabyte
          Assert.AreNotEqual(0, customerLease.CustomerLeaseTerm.AdditionalDataTransferCost);
   }
 
}

The preferred method for resolving runtime dependencies is by using constructor based DI. There is no real difference between the two except; Using a service locator allows for lazy object instantiation at runtime. This is super useful if you have a Dependency which cannot be resolved upon construction.

Open for comments or suggestions?


Comment Form

About Justin

justin

Justin is a Senior Software Engineer living in Brisbane. A Polyglot Developer proficient in multiple programming languages including [C#, C/C++, Java, Android, Ruby..]. He's currently taking an active interest in Teaching Kids to Code, Functional Programming, Robotics, 3D Printers, RC Quad-Copters and Augmented Reality.

About This Blog

Software Engineering is an art form, a tricky art form that takes as much raw talent as it does technical know how. I'll be posting articles on professional tips and tricks, dos and donts, and tutorials.

profile for Justin Shield on Stack Exchange, a network of free, community-driven Q&A sites

Photostream

  • What I look for in a senior software engineer Justin Shield: […] I’m not going to list the design patterns that you’ll need, I’ve already [...]
  • Justin: Hi Ross, I do actually like Umbraco, it provides some nice abilities for creating websites that I [...]
  • Justin: Hi GordonBGood, Thanks for taking the time in replying. You're absolutely correct, it is turners s [...]
  • Ross Gallagher: Hi Justin, I'm a fellow Aussi looking to use Umbraco to create a simple website. I have downloaded [...]
  • GordonBGood: This is the "Turner Sieve" which **IS NOT** the Sieve of Eratosthenes (SoE) neither by algorithm nor [...]