单元测试IUnityContainer.Resolve

dpa*_*ons 0 c# unit-testing dependency-injection rhino-mocks unity-container

我有一个使用Unity for DI的应用程序但我在编写单元测试时遇到了一些麻烦.在我的一些业务层方法中,我有与此类似的代码:

var obj = container.Resolve<ISomeObj>();
Run Code Online (Sandbox Code Playgroud)

这要么是站在一个最终会传递给数据库的内存中对象,要么是最终传递给客户端的内存中对象.但问题是RhinoMocks(貌似)无法正确地模拟容器,所以做这样的事情:

 mockContainer = MockRepository.GenerateMock<IUnityContainer>();
 mockContainer.Expect(x => x.Resolve<ISomeObj>())
            .Return(mockObj);
Run Code Online (Sandbox Code Playgroud)

在这里获得异常似乎是有道理的,因为容器实际上是空的,但我没有看到解决问题的直接方法.我曾考虑用包装器抽出容器以解决这个问题,但这似乎有点矫枉过正.

任何想法或建议都非常感谢!

- - 编辑 - -

由于Yacoub发布了他的答案,我一直在阅读有关服务定位器(反)模式的一些内容,虽然人们普遍认为这是一种反模式,但我还没有找到关于如何处理POCO的答案.

使用上面的例子,似乎我的问题的一般答案是做这样的事情:

public class Foo()
{
    private ISomeObj someObj;
    public Foo(ISomeObj injectObj)
    {
        someObj = injectObj;
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为我对此方法的唯一抱怨是它(可能)使构造函数"忙"ala:

public class Foo()
{
    public Foo(ISomeService injectSvc, ISomeObj injectObj, ISomeObj2 injectObj2, ISomeObj3 injectObj3)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,除非我遗漏了某些内容,否则我需要一种方法来重新初始化给定的实例以供重用.含义:如果MethodA()和MethodB()都使用了ISomeObj,当MethodA()完成ISomeObj时,我需要重新初始化ISomeObj中的所有字段,以便MethodB()可以完成它的工作.

解决这个问题的"最佳"方法是什么?

Yac*_*sad 5

您正在做什么(使用业务层方法内部的容器解析对象)称为服务位置,并被视为反模式.您可能需要考虑重构以使用构造函数注入.如果你这样做,那么你就不需要在单元测试中使用容器了.

话虽如此,如果没有这样的重构,你可以做到这一点:不要嘲笑容器.相反,使用一个真正的容器,并使用容器注册模拟实例,如下所示:

container.RegisterInstance<ISomeObj>(mockObj); //mockObj is the mocking object that implements ISomeObj
Run Code Online (Sandbox Code Playgroud)

为此interface(ISomeObj)完成的所有解析操作都将返回相同的实例.

如果您需要能够为每个解析操作获取新实例,则可以执行以下操作:

container.RegisterType<ISomeObj>(new InjectionFactory(x => GenerateMock()));
Run Code Online (Sandbox Code Playgroud)

GenerateMock创建模拟对象的方法在哪里.您可以使用RhinoMocks创建模拟的代码替换此调用.