I already mentioned about AutoFixture in one of the posts – Lightning talk – Autofixture. Main goal of this library is to help us with reduction of Arrange part of unit tests. With this library we can focus on the main scenario of unit test instead of focusing on building objects that are needed for test. Moreover AutoFixture will protect us against modification of classes that are being used in our unit tests.
But it is not perfect. Sometimes duration of unit tests can increase dramatically. Especially when you are creating objects used by EntityFramework.
Of course there is a solution for this issue. And I would like to share with you with this solution. We need only to write code that will tell AutoFixture to ignore construction objects that are marked as virtual in classes. To do that we need to first implement own SpecimenBuilder:
public class IgnoreVirtualMembersSpecimenBuilder : ISpecimenBuilder { public object Create(object request, ISpecimenContext context) { var propertyInfo = request as PropertyInfo; if (propertyInfo == null) { return new NoSpecimen(); } if (propertyInfo.GetGetMethod().IsVirtual) { return null; } return new NoSpecimen(); } }
And then configure AutoFixture to use our IgnoreVirtualMembersSpecimenBuilder:
var fixture = new Fixture(); fixture.Customizations.Add(new IgnoreVirtualMembersSpecimenBuilder());
Provided solution works in most cases. You need to remember only about default behaviour of CLR. Each time when your class implements interface all items that are from interface are marked as virtual. This means that the Fixture that is using our builder will return null value for each of those items. Please look at following example:
public interface IUser { string Name { get; set; } string Surname { get; set; } } public class User : IUser { public string Name { get; set; } public string Surname { get; set; } }
And here is unit test that is presenting described behaviour:
[Fact] public void IssueWithClassThatImplementsInterface() { // Arrange var fixture = new Fixture(); fixture.Customizations.Add(new IgnoreVirtualMembersSpecimenBuilder()); // Act var user = fixture.Create<User>(); // Assert Assert.Null(user.Name); Assert.Null(user.Surname); }
Please remember that described solution will allow you to speed up you unit tests especially when you are using AutoFixture for EntityFramework object creation.
Thank you!! This saved me! 2
Thank you!! This saved me!