The Better .NET Unit Tests with AutoFixture: Get Started course by Jason Roberts, takes you through the need for and use of AutoFixture. AutoFixture is an open source library that helps you to create anonymous test data to accelerate your unit testing time frame. The ability that AutoFixture provides to quickly and easily generate anonymous test data is also a great addition to moving towards TDD. I am definitely a proponent of utilizing a TDD methodology, a tool like AutoFixture certainly helps to reduce the resistance by making the data setup much easier. This course will get you up and running with AutoFixture quickly, by taking you through all of the basic and some important advanced usages you may need to understand to get AutoFixture integrated into your project.
Introducing AutoFixture
- Improve readability
- Generate anonymous test data – data we don’t really care about
- Improve productivity – reduce the need to manually create up test data not imperative to test itself
- Reduce test maintenance
- Reduce TDD friction
- Small constant changes should not cause tests to break
- Reduce “Arrange” test code
- Arrange signifies the phase where the test data/state of system under test is being setup
- Anonymous test data
- “Data that is required to be present for the test to be able to execute, but where the value itself is unimportant.”
- Can be used with any test framework
- Additional nuget packages that add support for specific frameworks
- The “Fixture” class
- [csharp]Create()[/csharp] – creates anonymous test data
- Properties on custom objects will be populated with anonymous data as well
Creating Anonymous Test Data
- Strings
- [csharp]var name = fixture.Create()[/csharp]
- Generates a random “guid” for a string – sometimes this will make it difficult to understand a failed test
- [csharp]var name = fixture.Create(“first_”)[/csharp] – put in a “seed” string – prefix the anonymous value with seed value
- [csharp]var anonymousChar = fixture.Create()[/csharp]
- Â Numbers
- [csharp]var num = fixture.Create()[/csharp] – suppports all numeric types (double/decimal/long/short…etc)
- Dates and Times
- [csharp]var dt = fixture.Create()[/csharp]
- [csharp]var ts = fixture.Create()[/csharp]
- Sequences and Complex Types (Collections) – Also applies to Custom Objects
- [csharp]var msgs = fixture.CreateMany()[/csharp]
- [csharp]var msgs = fixture.CreateMany(10)[/csharp] – create 10 strings (3 is default)
- [csharp]fixture.AddManyTo(sut.Messages, 10)[/csharp] – generate 10 strings and add to existing collection on system under test
- [csharp]fixture.AddManyTo(sut.Messages, () => “hi”)[/csharp] – creator method – creates collection with “hi” 3 times
- Custom/Complex Objects
- [csharp]var myObj = fixture.CreateMany()[/csharp]
- All public properties will be created and defaulted as well
- Autofixure respects DataAnnotations
- Example string has [csharp][StringLength(8)][/csharp] – auto fixture will create a string with at most 8 characters
Customizing Object Creation
- [csharp]fixture.Inject(“LHR”)[/csharp] – allows injection of a type of value for ALL instances
- Everytime the fixture tries to create an anonymous string it will use LHR
- You can also inject complex objects which would function the same way
- [csharp]var customObj = fixture.Build().Create();[/csharp]
- Build gives you control over how properties are instantiated by autofixture
- Create must be called at the end of the chain
- [csharp].Without()[/csharp] – will stop a property from being auto populated
- You can also perform actions with the “do” method added to the chain
- Autofixture Pipeline
- Custom Property Specimen builder – inject a builder into the pipeline to run custom code to set a property
- [csharp]fixture.Customizations.Add(new CustomSpecimenBuilder())[/csharp] – this will include in the fixture pipeline
Writing Less Test Code and Improving Test Maintenance
- AutoData attribute – Pass auto generated data into parameterized test
- Can also create SUT by adding a parameter for it
- InlineAutoData attribute – [csharp][InlineAutoData(-5)][/csharp]
- List the number of parameters you want to populate, all other will be populated automatically by autofixture
- By default if an object has a dependency on an interface autofixture cannot create that object because it does not know how to inject the proper class
- Autofixture with auto mocking nuget package
- [csharp]fixture.Customize(new AutoMoqCustomization())[/csharp] – will automock interfaces
- [csharp]fixture.Freeze<Mock<ICustomObj>>()[/csharp] – gets reference to the automocked object for use in asserts
- AutoMoqData – custom attribute to parameterize a test and have all setup data passed in
- When parameterizing need to use [csharp][Frozen][/csharp] attribute to get a reference to any expected mocked object