我目前正在学习DI & Mocking,使用Unity和NSubstitute。我还使用了一个取自这个问题的自动锁定扩展:Is this possible with Unity (Instead of Castle Windsor)?
在下面的单元测试中,我尝试从我的方法Add()中设置一个NSubstitute返回值10。但是,当通过控制器调用进行调试时,分配的值是默认值0,而不是预期的10。代理似乎没有截获方法调用。
我怀疑这是因为没有正确注册我的类型/容器,有谁能给我指出正确的方向吗?
[TestFixture]
public class ApplicationControllerTests
{
private IUnityContainer _container;
private ApplicationController _controller;
private ISampleService _sampleService;
[SetUp]
public void SetUp()
{
_container = new UnityContainer().AddExtension(new AutoMockingContainerExtension());
_controller = _container.Resolve<ApplicationController>();
_sampleService = _container.Resolve<ISampleService>();
}
[Test]
public void TestSampleService()
{
// This line is not working
_sampleService.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(10);
var result = _controller.Index();
_sampleService.Received().Add(Arg.Any<int>(), Arg.Any<int>());
}
}
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer _container;
public AutoMockingBuilderStrategy(IUnityContainer container)
{
_container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !_container.IsRegistered(key.Type))
context.Existing = CreateSubstitute(key.Type);
}
private static object CreateSubstitute(Type type)
{
return Substitute.For(new[] { type }, null);
}
}
}和我的控制器代码
public class ApplicationController : BaseController
{
private readonly ISampleService _sampleService;
public ApplicationController(ISampleService sampleService)
{
_sampleService = sampleService;
}
public ActionResult Index()
{
var result = _sampleService.Add(2, 3);
// result is 0, expected 10 ??
return View();
}
}
public interface ISampleService
{
int Add(int first, int second);
}
public class SampleService : ISampleService
{
public int Add(int first, int second)
{
return first + second;
}
}发布于 2012-11-14 14:23:28
实际上,Tormod是对的,问题是每当有人从容器中请求一个时,AutoMockingBuilderStrategy 都会返回一个不同的模拟实例。
所以在我的original implementation中有一个bug,即AutoMockingBuilderStrategy没有存储创建的模拟:
下面是一个固定的版本:
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer container;
private readonly Dictionary<Type, object> substitutes
= new Dictionary<Type, object>();
public AutoMockingBuilderStrategy(IUnityContainer container)
{
this.container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !container.IsRegistered(key.Type))
{
context.Existing = GetOrCreateSubstitute(key.Type);
context.BuildComplete = true;
}
}
private object GetOrCreateSubstitute(Type type)
{
if (substitutes.ContainsKey(type))
return substitutes[type];
var substitute = Substitute.For(new[] {type}, null);
substitutes.Add(type, substitute);
return substitute;
}
}
}发布于 2012-11-14 14:11:47
我怀疑您正在处理两个不同的ISampleService实例,它们分别在设置的第2行和第3行创建。为了进行测试,您可以将_sampleServie字段设置为公共字段,然后在第三行Setup()中尝试
_sampleService = _controller._sampleService;https://stackoverflow.com/questions/13373302
复制相似问题