首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSubstitute和统一

NSubstitute和统一
EN

Stack Overflow用户
提问于 2012-11-14 13:00:15
回答 2查看 2.9K关注 0票数 2

我目前正在学习DI & Mocking,使用Unity和NSubstitute。我还使用了一个取自这个问题的自动锁定扩展:Is this possible with Unity (Instead of Castle Windsor)?

在下面的单元测试中,我尝试从我的方法Add()中设置一个NSubstitute返回值10。但是,当通过控制器调用进行调试时,分配的值是默认值0,而不是预期的10。代理似乎没有截获方法调用。

我怀疑这是因为没有正确注册我的类型/容器,有谁能给我指出正确的方向吗?

代码语言:javascript
复制
[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);
        }
    }
}

和我的控制器代码

代码语言:javascript
复制
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;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-14 14:23:28

实际上,Tormod是对的,问题是每当有人从容器中请求一个时,AutoMockingBuilderStrategy 都会返回一个不同的模拟实例。

所以在我的original implementation中有一个bug,即AutoMockingBuilderStrategy没有存储创建的模拟:

下面是一个固定的版本:

代码语言:javascript
复制
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;
        }
    }
}
票数 4
EN

Stack Overflow用户

发布于 2012-11-14 14:11:47

我怀疑您正在处理两个不同的ISampleService实例,它们分别在设置的第2行和第3行创建。为了进行测试,您可以将_sampleServie字段设置为公共字段,然后在第三行Setup()中尝试

代码语言:javascript
复制
_sampleService = _controller._sampleService;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13373302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档