I am currently trying to learn DI & Mocking, with Unity and NSubstitute. I am also using an automocking extension taken from this question: Is this possible with Unity (Instead of Castle Windsor)?
In my unit test below I am trying to set an NSubstitute return value of 10 from my method Add(). However when debugging through the controller call the assigned value is the default 0 rather than the expected 10. The proxy does not seem to be intercepting the method call.
I suspect this is caused by not registering my Types/container correctly, anybody able to point me in the right direction?
[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);
}
}
}
And my controller code
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;
}
}
Actually Tormod is right the problem is that the
AutoMockingBuilderStrategyreturns a different mock instance every time when somebody requests anISampleServiceform the container.So there is a bug in my original implementation namely the
AutoMockingBuilderStrategydoesn’t store the created mocks:Here is a fixed version: