1

I have a simple structure of classes, interfaces as follows:

public interface IMessagingClient (interface supporting service bus queue operation)

public class ServiceBusMessagingClient : IMessagingClient     (real implementation)

public class MockMessagingClient : IMessagingClient    (mock implementation for our unit test)

public class FailoverMessagingClient : IMessagingClient       (this implementation internally uses 2 clients and switches roles b/w 2 as and when disaster in a datacenter occur)
{
private IMessagingClient PrimaryClient { get; set; }
private IMessagingClient SecondaryClient { get; set; }
}

We load unity config from web.config/app.config and use it in our product code and test code.

We want following:

  • For production scenario, PrimaryClient and SecondaryClient should of type ServiceBusMessagingClient

  • For Test scenario, PrimaryClient and SecondaryClient should of type MockMessagingClient

Our current unity config looks like:

<container name="azure">
 <register type="IMessagingClient" mapTo="FailoverMessagingClient"/>
</container>

Do we have to use some interceptors to achieve this? Or by defining a ctor in FailoverMessagingClient and using ctor injection?

Some suggestions would be great!

2 Answers 2

3

You can do this using named registrations.

For example, given the following example set up:

namespace ConsoleApplication8
{
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;

    public interface IMessagingClient { }

    public class ServiceBusMessagingClient : IMessagingClient { }

    public class MockMessagingClient : IMessagingClient { }

    public class FailoverMessagingClient : IMessagingClient
    {
        private readonly IMessagingClient primaryClient;
        private readonly IMessagingClient secondaryClient;

        public FailoverMessagingClient(IMessagingClient primaryClient, IMessagingClient secondaryClient)
        {
            this.primaryClient = primaryClient;
            this.secondaryClient = secondaryClient;
        }
    }

    class Program
    {   
        static void Main(string[] args)
        {
            var container = new UnityContainer().LoadConfiguration();

            var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");

        }
    }
}

you can hook up the dependencies using the app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="IMessagingClient" type="ConsoleApplication8.IMessagingClient, ConsoleApplication8" />
    <alias alias="ServiceBusMessagingClient" type="ConsoleApplication8.ServiceBusMessagingClient, ConsoleApplication8" />
    <alias alias="MockMessagingClient" type="ConsoleApplication8.MockMessagingClient, ConsoleApplication8" />
    <alias alias="FailoverMessagingClient" type="ConsoleApplication8.FailoverMessagingClient, ConsoleApplication8" />
    <container>
      <register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />
      <register type="IMessagingClient" name="Two" mapTo="FailoverMessagingClient">
        <constructor>
          <param name="primaryClient">
            <dependency type="IMessagingClient" name="One" />
          </param>
          <param name="secondaryClient">
            <dependency type="IMessagingClient" name="One" />
          </param>
        </constructor>
      </register>
    </container>
  </unity>

</configuration> 

Changing the line

<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />

to

<register type="IMessagingClient" name="One" mapTo="MockMessagingClient" />

will allow you to swap out your implementation of IMessagingClient as appropriate.

Personally, I would rather do this using the fluid syntax

    var container = new UnityContainer();
    container.RegisterType<IMessagingClient, ServiceBusMessagingClient>("One");

    container.RegisterType<IMessagingClient, FailoverMessagingClient>("Two", 
        new InjectionConstructor(new ResolvedParameter<IMessagingClient>("One"), new ResolvedParameter<IMessagingClient>("One")));

    var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");
Sign up to request clarification or add additional context in comments.

Comments

0

When using the unity container, you can override an existing registration by registering it again for a different class.

For example:

If you run this code:

container.RegisterType<IMessagingClient, ServiceBusMessagingClient>();
container.RegisterType<IMessagingClient, MockMessagingClient>();

The first registration is overridden and so IMessagingClient is mapped to MockMessagingClient. Its like the first line never executed.

You can use this fact, and in your unit test (in the arrange phase or in the setup method of your test class), simply register the IMessagingClient to the mock implementation like this (after loading the XML configuration):

container.RegisterType<IMessagingClient, MockMessagingClient>();

By the way, you might not want to use DI containers in unit tests. Take a look at this question.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.