Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock (with Moq) Unity methods

Extension methods are not good for testing (that's described here: Mocking Extension Methods with Moq, http://www.clariusconsulting.net/blogs/kzu/archive/2009/12/22/Howtomockextensionmethods.aspx).

But probably there are some solutions for mocking of Unity methods? In my case I have the following function:

public class MyManager
{
    public MyManager(IUnityContainer container) : base(container) { }

    public IResult DoJob(IData data)
    {
        IMyLog log = MyContainer.Resolve<IMyLog>();

        ... use log.Id ...

        MyContainer.Resolve<...>();//usage for other purposes...
    }

I want to be sure that 'DoJob' method will always get 'IMyLog' object from container, but not from other sources... how could I test that?

My original idea was to change 'DoJob' method implementation and use:

IMyLog log = UnityContainer.Resolve(typeof(IMyLog)) as IMyLog;

But 'Resolve(Type t, ...)' is also an extension method...

Any thoughts are welcome.

P.S. Please note, that 'my log' object is created far-away from MyManager.DoJob...

like image 218
Budda Avatar asked Sep 24 '10 22:09

Budda


2 Answers

I know I'm late to the party, but I had the same problem, and resolved it by mocking out the following method -

IUnityContainer.Resolve(Type t, string name, params ResolverOverride[] resolverOverrides);

For example -

unityMock = new Mock<IUnityContainer>(MockBehavior.Strict);
validatorMock = new Mock<IValidator>(MockBehavior.Strict);
unityMock.Setup(p => p.Resolve(typeof(IValidator), null))
     .Returns(validatorMock.Object);

Just in case someone needs to mock this out and can't remove the dependency on the container.

like image 72
Jamie Burns Avatar answered Sep 22 '22 13:09

Jamie Burns


Remove the dependency on IUnityContainer and things become a lot easier and cleaner. Instead let unity inject your dependencies which are abstracted into interfaces. These are easily mocked. Here's an example using a little trick with Unity that injects an auto-factory for IMyLog.

public class MyManager
{
   private readonly Func<IMyLog> logFactory;

   public MyManager(Func<IMyLog> logFactory) 
   {
       this.logFactory = logFactory;
   }

   public IResult DoJob(IData data)
   {
       IMyLog log = logFactory();

       ...
   }
}

Or if you don't need to create the instance each time:

public class MyManager
{
   private readonly IMyLog myLog;

   public MyManager(IMyLog myLog) 
   {
       this.myLog = myLog;
   }

   public IResult DoJob(IData data)
   {
       ...
   }
}
like image 21
TheCodeKing Avatar answered Sep 18 '22 13:09

TheCodeKing