2

I have a following scenario:

public void DoSomething(...)
{
   ...
   ClassA obj1 = new ClassA();
   ClassB obj2 = new ClassB();
   ClassC obj3 = new ClassC();
   ...
}

I understand that if I was using Dependency Inversion Principle, I could Mock the interface and it will work. The issue is that these instances are needed Only in this method, so it doesn't make sense to create them at class level. On top of that, some methods have 5-6 object declarations, so passing these as parameters will bloat up the parameter list.

Is there anyway I can use Moq, NMock etc to Mock these classes (which are based off of a common interface)?

tunafish24
  • 2,288
  • 6
  • 28
  • 47

2 Answers2

2

If you only need to instantiate those types in that method, you're right in that they shouldn't be injected into the class.

Instead, the typical solution is to inject a factory that will allow your method to resolve an interface.

Here's the usual approach:

interface IMessageFactory
{
    IMessage CreateMessage(string text);   
}

class ConcreteMessageFactory : IMessageFactory
{
    IMessage CreateMessage(string text) { return new Message(text); }
}

class MockMessageFactory : IMessageFactory
{
    public IMessage CreateMessage(string text) { return new MockMessage(text); }
}


class MyClient
{
    private readonly IMessageFactory _msgFactory;

    public MyClient(IMessageFactory msgFactory)
    {
        _msgFactory = msgFactory;   
    }

    public void SendMessage(string text)
    {
        IMessage msg = _msgFactory.CreateMessage(text);
        msg.Send();
    }
}


//Usage:
new MyClient(new ConcreteMessageFactory());
//Mocking
new MyClient(new MockMessageFactory());

Depending on which DI framework you're using, the framework can make this way easier for you. Castle Windsor, for example, lets you inject a delegate-based factory, as opposed to the interface-based factory above:

class MyClient
{
    private readonly Func<string, IMessage> _msgFactory;

    public MyClient(Func<string, IMessage> msgFactory)
    {
        _msgFactory = msgFactory;   
    }

    public void SendMessage(string text)
    {
        IMessage msg = _msgFactory(text);
        msg.Send();
    }
}

//Usage:
new MyClient(() => new Message());
//Mocking
new MyClient(() => new MockMessage());
dcastro
  • 66,540
  • 21
  • 145
  • 155
1

You can use something like StructureMap to do the work for you, your method would become something like.

public void DoSomething(...)
{
   ...
   IClassA obj1 = ObjectFactory.GetInstance<IClassA>();
   IClassB obj2 = ObjectFactory.GetInstance<IClassB>();
   IClassC obj3 = ObjectFactory.GetInstance<IClassC>();
   ...
}

Then normally you'd map them like this in global.asax or similar

        ObjectFactory.Initialize(x =>
        {
            x.ForRequestedType<IClassA>().TheDefaultIsConcreteType<ClassA>();
            ...etc
        });

But for your unit tests

        ObjectFactory.Initialize(x =>
        {
            x.ForRequestedType<IClassA>().TheDefaultIsConcreteType<UnitTestClassA>();
            ...etc
        });
Klors
  • 2,665
  • 2
  • 25
  • 42