1

这篇文展示了一种使用 Castle Windsor 和 NSubstitute 实现自动模拟的方法。

我不知道也不使用 Castle Windsor,但我确实使用 Unity 和 NSubstitute。

有没有办法用 Unity 做他展示的事情?


以下是帖子的相关内容:

首先,在 Windsor 中注册一个 ILazyComponentLoader:

var c = new WindsorContainer();    
c.Register(Component.For<LazyComponentAutoMocker>());

那么,LazyComponentAutoMocker 的实现就很简单了:

public class LazyComponentAutoMocker : ILazyComponentLoader
{    
  public IRegistration Load(string key, Type service, IDictionary arguments)    
  {    
    return Component.For(service).Instance(Substitute.For(new[] { service }, null));    
  }    
}

你完成了!这是一个简单的单元测试示例,仅使用上面的代码:

[Test]
public void IDictionary_Add_Invoked()
{
  var dict = c.Resolve<IDictionary>();
  dict.Add(1, 1);
  dict.Received().Add(1, 1);
}
4

1 回答 1

3

使用 Unity,您可以编写一个自定义容器扩展来进行自动模拟。

根据这篇文章,您需要以下内容:

编辑:我的实现示例中有一个错误:请参阅这个 SO 问题NSubstitute 和 Unity

所以固定的代码如下所示:

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;
        }
    }
}

你可以在创建你的容器时注册它:

IUnityContainer container = new UnityContainer();
container.AddExtension(new AutoMockingContainerExtension());
于 2012-05-16T22:23:20.997 回答