Is this possible with Unity (Instead of Castle Windsor)?

本小妞迷上赌 提交于 2019-12-20 04:59:43

问题


This blog post shows a way to implement auto mocking with Castle Windsor and NSubstitute.

I don't know or use Castle Windsor, but I do use Unity and NSubstitute.

Is there a way to do what he shows using Unity?


Here is relevant content of the post:

First of all, register an ILazyComponentLoader into Windsor:

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

Then, the implementation of LazyComponentAutoMocker is simply this:

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

And you’re done! Here’s a simple unit test example using only the code from above:

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

回答1:


With Unity you can write a custom container extension which does the automocking.

Based on this article, you need something like:

EDIT: There was a bug in my implementation sample: see this SO question: NSubstitute and Unity

So the fixed code looks like this:

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

And you can register it when creating your cotainer:

IUnityContainer container = new UnityContainer();
container.AddExtension(new AutoMockingContainerExtension());


来源:https://stackoverflow.com/questions/10627406/is-this-possible-with-unity-instead-of-castle-windsor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!