TIL: How to register an implementation of a generic interface in AutoFixture
Pedro Osternack CorrĂȘa
Posted on June 7, 2021
On a previous post I've used AutoFixture
with a auto mocking customization (that would generate mocks for each dependency of the system under test (SUT) that you create through AutoFixture). On that post I had one snippet that used the Register
method, like this:
// Initializing each mocks manually and use AutoFixture for the SUT
private ServicyMcServiceFace CreateFixtureSemiAuto()
{
var fixture = new Fixture();
var dep1 = new Mock<IDependency1>();
fixture.Register(dep1.Object);
return fixture.Create<ServicyMcServiceFace>();
}
I did not gave muck attention to that method at the time, but recently I had to use it in a different manner so I decided to share it.
On the example above we have a service that have a service that has a dependency of type IDependency1
. By registering the Mocked object with the fixture we're basically configuring it as our dependency injection (DI) container (or Inversion Of Control Container) and telling it to use that Mock every time someone asks for the IDependency1
interface. The same can be done with a real implementation of the interface, but instead of passing the mocked object we would pass a new instance of the implementing class.
So far so good.
But if we have a generic interface as our dependency that method overload will not work.
// Constructor for ServicyMcServiceFace
public ServicyMcServiceFace(IConverter<Type1, Type2> converter)
{ ... }
// The implementation or our dependency that we want to use on our test
public class T1toT2Converter: IConverter<Type1, Type2> { ... }
On this example our SUT depends the a converter between Type1
and Type2
, and we want to use the T1toT2Converter
implementation of that interface on our tests (there are many reasons why one would prefer to do that instead of using a mock, but this discussion if beyond the point of this post). We can easily register that with in our fixture
by using one of the generic overloads of the Register
method as follows.
private ServicyMcServiceFace CreateFixtureSemiAuto()
{
var fixture = new Fixture();
// registering our interface implementation.
fixture.Register<IConverter<Type1, Type2>>(() => new T1toT2Converter());
return fixture.Create<ServicyMcServiceFace>();
}
And there you go. Now every time you create a new instance of the SUT through the fixture it will receive a new instance of the converter.
If you want to use just one instance of the dependency you can just instantiate the dependency, save it to a field on your test suit and pass that in the Register callback method, for example.
The Register
method is way more powerful than I make it appear here, and it gives a lot of options to customize how AutoFixture
will generate your fixtures. I highly recommend reading the articles form Mark Seeman's blog that I'll add to the references at the end of this post.
So that's that for now, I hope this can be useful.
References:
Dealing With Types Without Public Constructors
Replacing AutoFixture's Default Algorithms
Posted on June 7, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.