我通过构造函数注入使用IoC容器而不是DI。有些人可能会问我为什么使用IoC容器而不是构造函数注入。嗯,原因如下:Why do I need an IoC container as opposed to straightforward DI code?。 但是,我发现很难为我的服务创建单元测试。我不确定如何在运行时模拟我的服务使用的存储库,因为我没有使用构造函数注入(一个难题)。有人有任何解决方案?
例如:
public class SomeService
{
private ISomeServiceRepository someServiceRepository;
public GetSomeThing()
{
//how do I mock this repository in my unit test
someServiceRepository = IoC.Resolve<ISomeServiceRepository>();
someData = someServiceRepository.getData();
someOtherService = new SomeOtherService();
someThing = someOtherService.GetSomeThing();
return FigureOutSomeThingElse(someData, someThing);
}
public FigureOutSomeThingElse(someData, someThing)
{
//do some figuring
return somethingElse;
}
}
public class SomeOtherService
{
private ISomeServiceRepository someOtherServiceRepository;
public GetSomeThing()
{
//how do I mock this repository in my unit test
someOtherServiceRepository = IoC.Resolve<ISomeOtherServiceRepository>();
var someData = someOtherServiceRepository.getData();
return someData;
}
}
答案 0 :(得分:2)
人们可以根据需要轻松地解决关于“你做错了”的问题,但是我已经经历了旧代码库的痛苦,这种代码库无法无法理解寄存器解析 - 释放模式。但是,我建议不要使用静态容器引用(如在IoC.
中)并尝试使容器本身至少注入。
在这种情况下,您只需提供IoC注册容器的测试版本,但不是通常的应用程序配置,而是编写测试配置。
这不会是真正意义上的嘲弄或抄袭,实际上这些术语可能会使解决方案相当混淆。
实质上,在单元测试中它只是一个不同的活动配置。您仍然需要手动注册类型,如果它位于单元测试的执行路径中,您可能无法禁用当前配置代码。
我们有一个容器可以根据需要在IoC模式中解决(对于少数几种类型),并且为了测试我们只是创建了一个新容器(基本上,一个用于代码的配置和另一个用于单元测试的配置)。我们的用例略有不同,因为我们将容器注入类而不是像您的情况那样具有静态可访问类型。
答案 1 :(得分:2)
你真的不应该在你的类方法中使用IOC.Resolve。无论如何,它非常接近new
你的代码,这是你试图避免使用DI的一部分。写一个更好,更可测试的方法就是这样。
Public Class SomeService
{
ISomeServiceRepository someServiceRepository;
public SomeService(ISomeServiceRepository someServiceRepository)
{
this.someServiceRepository = someServiceRepository
}
Public GetSomeThing()
{
someData = someServiceRepository.getData();
...
}
}
通过这种方式,您可以模拟您的界面并直接注入它。
如果你必须使用.Resolve
,那么亚当的方法是你能做的最好的方法
答案 2 :(得分:0)
我明白了,这就是我做的......
(我正在使用Unity.Net和RhinoMock)
创建了一个实现IContainerAccessor的baseUnitTest类
在构造函数中创建并初始化UnityContainer的新实例
创建了一个“UnityContainer”readonly公共属性,它实现了IContainerAccessor.Container
创建了一个继承baseUnitTest的单元测试类
在测试方法中添加了以下代码......
Mocker = New Rhino.Mocks.MockRepository()
SomeRepository = Mocker.DynamicMock(OfomeomeRepository)()
MyBase.UnityContainer.RegisterInstance(OfomeomeRepository)(SomeRepository)
Rhino.Mocks.Expect.Call(Of SomeResult)(SomeRepository.SomeMethod(“someArg”))。Return(New SomeResult())
Mocker.ReplayAll()
someService = New SomeService()
'此方法使用IOC.Resolve(ISomeRepository)并调用SomeRepository.SomeMethod someResult = someService.someMethod()
Assert.IsNotNull(someResult)
完成