I am new to both libraries and before committing to their usage on a large project I need clarification on my options for low-code effort automocking in my unit tests.
After spending some time on Google I have concluded that, unlike some other IOC/Mocking product pairings, a ready-made plugin library is not available for LightInject+Nsubstitute to simplify the declaration of do-nothing default mocks in the arrange stage of a unit test.
I have read the LightInject docs on how to override a LightInject container with a temporary enhanced mock object just for the scope of a unit test but what about all the do-nothing default isolation mocks that a unit test might touch. Is there a way to automate their creation within the LightInject container?
The internal IOC container behaviour I am looking for is:
public class LightInject.ServiceContainer
{
..
public T GetInstance<T)
{
if (( this.RegisteredInterfaces.Any( i => i.Itype == T ) == false )
&& ( this.TemporaryUnitTestOverrides.Any( i => i.Itype == T ) == false ))
&& ( /* this container is configured with an automocking delegate */ ))
return autoMockCreatorDelegate<T>.Invoke();
}
It seems like LightInject's IProxy and Interceptors provide some internal mock object building blocks but the Nsubstitute library is full featured in comparison.
Clarification on what I mean by default do nothing mock and an enhanced mock.
// default do nothing mock
var calculator = Substitute.For<ICalculator>();
// Enhanced mock that will return 3 for .Add(1,2)
var calculator = Substitute.For<ICalculator>();
calculator.Add(1, 2).Returns(3);
Obviously the second enhanced type of mock will need to be crafted locally per unit test.
I am the author of LightInject and would really like to help you out.
Let me look into this and get back to you. In the meanwhile you might want to check out this library at LightInject.AutopMoq which is a third party contribution to the LightInject container. It uses Moq instead of NSubstitute, but the general concept should be similar to what you are asking for.
That being said, I did some work a while ago that simplifies automocking even further and will take a look at it it and see how that can be integrated with NSubstitute.
Edit
This is a super simple automocking implementation that works with any "substitute" framework.
using System.Diagnostics;
using LightInject;
using NSubstitute;
public interface IFoo { }
class Program
{
static void Main(string[] args)
{
var serviceContainer = new ServiceContainer();
serviceContainer.RegisterFallback((type, s) => true, request => CreateMock(request.ServiceType));
var foo = serviceContainer.GetInstance<IFoo>();
Debug.Assert(foo is IFoo);
}
private static object CreateMock(Type serviceType)
{
return Substitute.For(new Type[] { serviceType }, null);
}
}
Best regards
Bernhard Richter