One of the least enticing things about the Assert phase in unit tests is to populate all the unnecessary variables that a method requires to function. Often, a Data Transfer Object (DTO) will have several variables that do not affect the test, but to compile the code we need to define them, this where AutoFixture enters!
As the AutoFixture creator, Mark Seemann describes it this way: "AutoFixture is designed to make Test-Driven Development more productive, and unit tests more refactoring-safe. It does so by removing the need for hand-coding anonymous variables as part of a test's Fixture Setup phase". AutoFixture creates values of any type without explicitly instantiate them. This way, we do not need to explicitly write and come up with a value for the test.
In the example above for IsWordUnit test, where we evaluate if an input word is different from "unit", we can write something like "notUnit" and the test will work, or we let AutoFixture automatically generate a word for the test. This feature becomes extremely useful because:
- 1. We do not need to come up with a random string. We know that in this case is just one string, but in more complex applications, some DTO's have several variables, and then we need to come up with even more values and for different types!
2. Each time we run the test, a different value will be generated. This particularity is useful (sometimes of course) since the value of the variables should be independent of the test. Besides "unit" any value should make the test pass. In the case of strings, AutoFixture uses a GUID as a value, so we know it will never be "unit".
In other tests, where variables do not affect the test, having different values every time we run the test, ensures the integrity of the code and makes for a better test.
The next piece of code shows how the previous test can be done using AutoFixture:
public void IsUnitWord_InputIsDifferentThanUnit_ReturnsFalse_AutoFixture()
var fixture = new Fixture();
var input = fixture.Create<string>();
var fooBar = new FooBar();
var result = fooBar.IsUnitWord(input);
Only the Arrange phase was changed, where we switched the "var input = "notUnit";" by "var input = fixture.Create<string>();”. The create method of AutoFixture will create a random value for the type that was specified, in this case, a string.
If it were a complex type, it would look something like "var input = fixture.Create<GiantDto>();” where GiantDto is a complex DTO with several variables, and AutoFixture would fill them with random values!
Furthermore, AutoFixture as a lot more features! For example, what happens if we need to have a specific value for a variable inside a DTO, but everything else can be random? AutoFixture already has that covered! AutoFixture has a method called "Build" where we can specify behaviour for every variable and/or types inside a specific DTO!
var expectedResult = fixture
.With(t => t.OneOfTheVariables, “specificString”)
And for us, this is one of the most powerful features of AutoFixture, where we can specify the behaviour that we want! We can specify by variable level, type level, or even class level!
AutoFixture offers even more features and extensions, and everything can be found in the official GitHub page of AutoFixture: https://github.com/AutoFixture/AutoFixture.