How to register dependencies that are not explicitly defined as Strict using AutoFixture with FakeItEasy?
I use AutoFixture with FakeItEasy when I need to test a class with many dependencies, but I decided to mock some of them. All other dependencies I prefer to mock with the Strict () FakeItEasy option. To make my test cleaner, I would like to mock only the dependencies I want and be able to specify that all dependencies that do not mock creation are created with Strict ().
In the example below, I would like to remove two lines of code that create the layout of IDependency2 but retain the same behavior: if the class under test calls any method on IDependency2, an exception will be thrown.
Any idea how to do this?
[TestFixture]
public class AutoTests
{
[Test]
public void Test()
{
// Arrange
IFixture fixture = new Fixture().Customize(new AutoFakeItEasyCustomization());
var dependency1 = fixture.Freeze<IDependency1>();
A.CallTo(() => dependency1.DoSomething()).Returns(12);
// I do not want to specify these two lines
var dependency2 = A.Fake<IDependency2>(s=>s.Strict());
fixture.Register(() => dependency2);
// Act
var classUnderTest = fixture.Create<ClassUnderTest>();
var actualResult = classUnderTest.MethodUnderTest();
// Assert
Assert.That(actualResult,Is.GreaterThan(0));
}
}
public class ClassUnderTest
{
private readonly IDependency1 _dependency1;
private readonly IDependency2 _dependency2;
public ClassUnderTest(IDependency1 dependency1, IDependency2 dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
public int MethodUnderTest()
{
return _dependency1.DoSomething()
+ _dependency2.DoSomething();
}
}
public interface IDependency1
{
int DoSomething();
}
public interface IDependency2
{
int DoSomething();
}
source to share
As a compromise solution, it is quite easy to implement a custom ISpecimenBuilder so that all auto- generated fakes are strict fakes. You can take a look at the standard Ploeh.AutoFixture.AutoFakeItEasy.FakeItEasyRelay fake builder to understand what's going on behind the curtain. The modified custom builder for strict forgeries is implemented as follows:
public class FakeItEasyStrictRelay : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (!this.IsSatisfiedBy(request))
return new NoSpecimen(request);
var type = request as Type;
if (type == null)
return new NoSpecimen(request);
var fakeFactoryMethod = this.GetType()
.GetMethod("CreateStrictFake", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod((Type) request);
var fake = fakeFactoryMethod.Invoke(this, new object[0]);
return fake;
}
public bool IsSatisfiedBy(object request)
{
var t = request as Type;
return (t != null) && ((t.IsAbstract) || (t.IsInterface));
}
private T CreateStrictFake<T>()
{
return A.Fake<T>(s => s.Strict());
}
}
It can simply be registered with the following expression:
IFixture fixture = new Fixture().Customize(
new AutoFakeItEasyCustomization( new FakeItEasyStrictRelay()));
source to share