I was debating whether to make this blog post because it’s so damn simple to implement, but hey, if it saves someone else time, I did some good.
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);}
That was almost too easy.
5 comments:
For what it's worth, I found this helpful. I'm new to Castle Windsor as well as NSubstitute. This post was able to get me going a lot quicker than sifting through documentation. Thanks.
Just wanted to say that this approach didn't work for me - I'm guessing it might have something to do with a newer version of Castle Windsor? I fixed it by registering the component like this instead (where square brackets are in fact angle brackets - the comment system didn't like angle brackets):
_container.Register(Component.For[ILazyComponentLoader]().ImplementedBy[LazyComponentAutoMocker]());
I needed this for integration testing my Web API application. I found that I had to reject loading concrete classes, or NSubstitute would choke on the controller classes. So my implementation ended up looking like this:
if (!(service.IsInterface || service.IsAbstract))
{
// Do not register instances for concrete types
return null;
}
var mock = Substitute.For(new[] {service}, null);
return Component.For(service).Instance(mock);
Post a Comment