单元测试:unitycontainer
本文关键字:unitycontainer 单元测试 | 更新日期: 2023-09-27 18:18:45
我有一个使用Unity进行DI的应用程序,但是我在编写单元测试时遇到了一点障碍。在我的几个业务层方法中,我有类似于下面的代码:
var obj = container.Resolve<ISomeObj>();
这要么是一个将最终传递给数据库的内存对象,要么是一个将最终传递给客户端的内存对象。但问题是,RhinoMocks(似乎)无法正确地模拟容器,因此可以这样做:
mockContainer = MockRepository.GenerateMock<IUnityContainer>();
mockContainer.Expect(x => x.Resolve<ISomeObj>())
.Return(mockObj);
在这里得到一个异常似乎是有意义的,因为容器实际上是空的,但我没有看到一个直接的方法来解决这个问题。我曾经考虑过用包装器抽象容器来解决这个问题,但这似乎有点过头了。
任何想法或建议都非常感谢!
——编辑——
自从Yacoub发表了他的答案后,我一直在阅读一些关于服务定位器(反)模式的文章,虽然它似乎被普遍接受为一种反模式,但我还没有找到关于如何处理poco的答案。
用我上面的例子,我的问题的一般答案似乎是这样做:
public class Foo()
{
private ISomeObj someObj;
public Foo(ISomeObj injectObj)
{
someObj = injectObj;
}
}
我想我对这种方法唯一的抱怨是它会(潜在地)使构造函数"忙碌",
public class Foo()
{
public Foo(ISomeService injectSvc, ISomeObj injectObj, ISomeObj2 injectObj2, ISomeObj3 injectObj3)
{
...
}
}
此外,除非我遗漏了什么,否则我需要一种方法来重新初始化给定的实例以供重用。含义:如果MethodA()和MethodB()都消耗ISomeObj,当MethodA()完成ISomeObj时,我需要以某种方式重新初始化ISomeObj中的所有字段,以便MethodB()可以做它的工作。
解决这个问题的"最佳"方法是什么?
您所做的(使用容器从您的业务层方法内部解析对象)称为服务定位,被认为是一种反模式。您可能需要考虑重构以使用构造函数注入。如果你这样做了,那么你就不需要在单元测试中使用容器了。
话虽如此,以下是您可以在不进行重构的情况下做的事情:不要模拟容器。相反,应该使用真正的容器,并向容器注册模拟实例,如下所示:
container.RegisterInstance<ISomeObj>(mockObj); //mockObj is the mocking object that implements ISomeObj
对该接口(ISomeObj
)执行的所有解析操作将返回相同的实例。
如果您需要能够为每个解析操作获得一个新的实例,您可以这样做:
container.RegisterType<ISomeObj>(new InjectionFactory(x => GenerateMock()));
其中GenerateMock
是创建模拟对象的方法。您可以使用使用RhinoMocks创建模拟的代码替换此调用。