I'm using AutoFixture with AutoMoqCustomization in my tests.
I have a service which is a dependency of the system under test:
ISomeService
{
Task<IEnumerable<int>> Get();
}
I call it inside the system under test:
var collection = await _someService.Get(); // collection is empty
I don't care what's inside the collection, but I need the collection not to be empty. I do it this way:
_fixture.Freeze<Mock<ISomeService>>()
.Setup(service => service.Get())
.Returns(Task.FromResult(_fixture.CreateMany<int>()));
It looks like it should be done with a customization. I created and registered one:
public class TaskCollectionCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new TaskCollectionBuilder(),
new GenericTypeSpecification(typeof(Task<>))));
}
private class TaskCollectionBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
// never enters here
}
}
}
The problem is it's Create method is never entered. Any ideas or ready-to-serve solutions?
EDIT
Adding GenericTypeSpecification source
public class GenericTypeSpecification : IRequestSpecification
{
private readonly Type _type;
public GenericTypeSpecification(Type type)
{
_type = type;
}
public bool IsSatisfiedBy(object request)
{
var requestedType = request as Type;
return requestedType != null &&
requestedType.IsGenericType &&
requestedType.GetGenericTypeDefinition() == _type;
}
}
AutoFixture already supports Tasks out of the box, as evidenced by this Characterization Test:
[Fact]
public void AutoFixtureAlreadySupportsTasks()
{
var fixture = new Fixture();
var t = fixture.Create<Task<IEnumerable<int>>>();
Assert.NotEmpty(t.Result);
}
Thus, all you need to configure a Test Double of your Service is something like this:
[Fact]
public void ConfigureMock()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
fixture.Freeze<Mock<ISomeService>>()
.Setup(s => s.Get())
.Returns(fixture.Create<Task<IEnumerable<int>>>());
var svc = fixture.Create<ISomeService>();
Assert.NotEmpty(svc.Get().Result);
}
If you think that's too much work, you can also ask AutoConfiguredMoqCustomization to do that for you instead, like this:
[Fact]
public void SimplestCustomization()
{
var fixture =
new Fixture().Customize(new AutoConfiguredMoqCustomization());
var svc = fixture.Create<ISomeService>();
Assert.NotEmpty(svc.Get().Result);
}
However, personally, I'm not a big fan of auto-configured Test Doubles, as I believe that explicit is better than implicit, and Test Double configuration ought to be an explicit part of a unit test, because it describes the Indirect Input for the test case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With