TIL: Using AutoFixture with auto mocking is awesome.
Pedro Osternack CorrĂȘa
Posted on March 5, 2021
I'm working on a .net core project and going through the tests I got my first contact with AutoFixture which is a tool that can ...create values of virtually any type without the need for you to explicitly define which values should be used.
So it can help with the creation of mock data (the main use I was aware of so far) and test doubles, making life a bit easier.
Today I've found out that it has an integration with the mocking library we're using, Moq
that makes it work as a DI container that provides mocks of dependencies for your classes.
ex.:
// Initializing each mocks and the SUT by hand
private ServicyMcServiceFace CreateFixtureFullManual()
{
var dep1 = new Mock<IDependency1>();
var dep2 = new Mock<IDependency2>();
var dep3 = new Mock<IDependency3>();
return new ServicyMcServiceFace(dep1.Object, dep2.Object, dep3.Object);
}
// Initializing each mocks manually and use AutoFixture for the SUT
private ServicyMcServiceFace CreateFixtureSemiAuto()
{
var fixture = new Fixture();
var dep1 = new Mock<IDependency1>();
var dep2 = new Mock<IDependency2>();
var dep3 = new Mock<IDependency3>();
fixture.Register(dep1.Object);
fixture.Register(dep2.Object);
fixture.Register(dep3.Object);
return fixture.Create<ServicyMcServiceFace>();
}
// Going full auto with AutoFixture.AutoMoq
private ServicyMcServiceFace CreateFixtureFullAuto()
{
// We configure the Fixture to use the necessary customization
var fixture = new Fixture().Customize(new AutoMoqCustomization());
return fixture.Create<ServicyMcServiceFace>();
}
As we can see above the SUT initialization became way simpler since we don't need to initialize each dependency by hand.
Now, what if we want to specify a behaviour for one of our mocks? Well, we can do that by using the freeze
method of our fixture
.
ex.:
[Test]
public void DoTheThing_Dep1ReturnsNegativeNumber_SignalsThatNegativeWasReceived()
{
// Initializing the fixture object with the AutoMoq Customization
var fixture = new Fixture().Customize(new AutoMoqCustomization());
// Freezes the instance of the IDependency1 Mock that will be used in this scope.
// With it we can set up the Mock and it will be used on the instantiation of our SUT later on.
fixture.Freeze<Mock<IDependency1>>().Setup(d => d.GetAnswer(), -42);
// The created object will receive the mock as we set up previously
var sut = fixture.Create<ServicyMcServiceFace>();
sut.DoTheThing();
Assert.True(sut.GotNegativeAnswer);
}
Awesome right? It makes life way simpler, mainly with you're dealing with Classes with tons of dependencies. I feel that the ability to use AutoFixture to manage all dependencies and only really get what you need when you need is a very powerful one and can make tests way simpler and a bit cleaner by removing a good amount of code from the setup step.
Hope this can be helpful to someone else.
Cheers.
Some sources:
Freezing mocks by Mark Seemann
AutoFixture as an auto-mocking container by Mark Seemann
Posted on March 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.