如何模拟(使用Moq)Unity方法

Bud*_*dda 13 .net extension-methods unit-testing moq mocking

扩展方法不适合测试(这里描述:使用Moq模拟扩展方法,http://www.clariusconsulting.net/blogs/kzu/archive/2009/12/22/Howtomockextensionmethods.aspx).

但是可能有一些模拟Unity方法的解决方案?在我的情况下,我有以下功能:

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...
    }
Run Code Online (Sandbox Code Playgroud)

我想确定'DoJob'方法总是从容器中获取'IMyLog'对象,但不是来自其他来源......我怎么能测试它?

我最初的想法是改变'DoJob'方法的实现和使用:

IMyLog log = UnityContainer.Resolve(typeof(IMyLog)) as IMyLog;
Run Code Online (Sandbox Code Playgroud)

但'Resolve(Type t,...)'也是一种扩展方法......

欢迎任何想法.

PS请注意,"我的日志"对象是远离MyManager.DoJob创建的...

Jam*_*rns 8

我知道我迟到了,但我遇到了同样的问题,并通过嘲笑以下方法解决了这个问题 -

IUnityContainer.Resolve(Type t, string name, params ResolverOverride[] resolverOverrides);
Run Code Online (Sandbox Code Playgroud)

例如 -

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

以防万一有人需要模拟这个并且无法删除对容器的依赖.


The*_*ing 6

删除对IUnityContainer的依赖,事情变得更容易和更清洁.相反,让团结注入被抽象为接口的依赖项.这很容易被嘲笑.这是一个使用Unity的小技巧为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();

       ...
   }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您不需要每次都创建实例:

public class MyManager
{
   private readonly IMyLog myLog;

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

   public IResult DoJob(IData data)
   {
       ...
   }
}
Run Code Online (Sandbox Code Playgroud)


Bud*_*dda 4

我猜,我找到了最合适的测试解决方案:没有必要模拟统一容器并检查是否从中获取“日志”对象。我只会为“Log”对象创建一个模拟,在容器中注册其对象实例,并检查测试是否确实使用了该日志对象。

这将完成所需的操作。

        Mock<IMyLog> mockLog = new Mock<IMyLog>();
        mockLog.Setup(mock=>mock.Id).Returns(TestLogId);

        IUnityContainer container = new UnityContainer();
        container
            .RegisterInstance(mockCommandExecutionLog.Object)
            ...
            ;

        ...

        mockLog.Verify(
            mock => mock.Id,
            Times.Once(),
            "It seems like 'Log' object is not used"
            );
Run Code Online (Sandbox Code Playgroud)

谢谢。