27
loading...
This website collects cookies to deliver better user experience
Write maintainable unit tests, faster.
AutoFixture makes it easier for developers to do Test-Driven Development by automating non-relevant Test Fixture Setup, allowing the Test Developer to focus on the essentials of each test case.
record Customer(Guid CustomerId, string FirstName, string LastName);
[Fact]
public void Should_create_a_customer()
{
var customer = new Customer(Guid.NewGuid(), "Sarah", "Dubois");
// act: create customer
// assert: verify customer has been created
}
record Customer(Guid CustomerId, string FirstName, string LastName, Address Address);
record Address(Guid AddressId, string Street, string PostalCode);
[Fact]
public void Should_create_a_customer()
{
var address = new Address(Guid.NewGuid(), "Place Georges-Pompidou 3", "75004 Paris");
var customer = new Customer(Guid.NewGuid(), "Sarah", "Dubois");
// act: create customer
// assert: verify customer has been created
}
[Fact]
public void Should_create_a_customer()
{
// With a factory method
var customer = CustomerHelpers.CreateCustomer();
// With the builder API
var customer = new CustomerBuilder().Build();
// act: create customer
// assert: verify customer has been created
}
record Customer(Guid CustomerId, string FirstName, string LastName, Address Address, IEnumerable<Order> Orders = default);
record Address(Guid AddressId, string Street, string PostalCode);
record Order(Guid OrderId, string ProductSku, int Amount);
Values are carefully generated to stay far away from any boundary conditions that may cause the SUT to behave differently in each test run.
Fixture
instance.Create
method to create an instance of a generic, in our example, a customer.[Fact]
public void Should_create_a_customer()
{
var fixture = new Fixture();
var customer = fixture.Create<Customer>();
// act: create customer
// assert: verify customer is created
}
Customer
object have a random value, even the nested Address
and Orders
objects.{
"CustomerId": "3b135dee-02f7-4e9b-9f15-7d5a79be460e",
"FirstName": "FirstName12320bc0-af71-4c81-bbf2-c468bdd9c0d9",
"LastName": "LastNamee46a8443-dcb0-41db-bc0b-331d8d7ba3cf",
"Address": {
"AddressId": "d251d392-200f-4cd8-a6f9-f51d2bb0adf0",
"Street": "Street81928752-4964-4816-b4cb-5624f54bae3c",
"PostalCode": "PostalCode959b3d36-1712-4f84-8a03-eb57427bca09"
},
"Orders": [
{
"OrderId": "de76756f-6c00-4707-9d8d-f883b802c44f",
"ProductSku": "ProductSkub905315a-a578-40c0-bf1a-023d5d2f6d02",
"Amount": 60
},
{
"OrderId": "b36a7f67-c980-45ec-955a-0a03beb78e79",
"ProductSku": "ProductSkuacd3cdb4-1ab4-42e1-8a47-807131ae73ab",
"Amount": 100
},
{
"OrderId": "bbd78fa6-d318-486d-a924-4b529dcbae9f",
"ProductSku": "ProductSku8348eca4-a98e-45c2-9c15-3d92202b9708",
"Amount": 29
}
]
}
AutoData
attribute that creates the fixtures for us. To use them, change the test from a Fact
to a Theory
and inject a customer as a parameter.[Theory]
[AutoData]
public void Should_create_a_customer(Customer customer)
{
// act: create customer
// assert: verify customer is created
}
[Theory, AutoData]
public void Should_create_a_customer(Customer customer)
{
customer.Orders = new List<Order>();
// act: create customer
// assert: verify customer is created
}
AutoDataAttribute
to provide the parameters to the test.With
method for each property that has to be overwritten, and assign it a value.NoOrdersDataAttribute
that contains a customer that has 0 orders.public class NoOrdersDataAttribute : AutoDataAttribute
{
public NoOrdersDataAttribute() : base(() => {
var fixture = new Fixture();
fixture.Customize<Customer>(transform => transform
.With(cust => cust.Orders, new List<Order>())
.With(cust => cust.FirstName, "Tim"));
return fixture;
}) { }
}
ICustomization
interface.public class NoOrdersCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Customer>(transform => transform
.With(cust => cust.Orders, new List<Order>())
.With(cust => cust.FirstName, "Tim"));
}
}
NoOrdersCustomization
to customize the fixture by replacing the inline customization with the new NoOrdersCustomization
class.public class NoOrdersDataAttribute : AutoDataAttribute
{
public NoOrdersDataAttribute() : base(() => new Fixture().Customize(new NoOrdersCustomization())){ }
}
[Theory]
[NoOrdersData]
public void Should_create_a_customer(Customer customer)
{
// customer.Orders is now an empty collection
// act: create customer
// assert: verify customer is created
}
ISpecimenBuilder
interface.ProductSku
.NoSpecimen
instance is returned.public class ProductSkuSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
return request switch {
PropertyInfo { Name: "ProductSku" } p when p.PropertyType == typeof(string) => $"Sku-{context.Create<string>()}",
_ => new NoSpecimen()
};
}
}
ProductSkuSpecimenBuilder
to the fixture created in the NoOrdersDataAttribute
.public class NoOrdersDataAttribute : AutoDataAttribute
{
public NoOrdersDataAttribute() : base(() => {
var fixture = new Fixture();
fixture.Customize(new NoOrdersCustomization());
fixture.Customizations.Add(new ProductSkuSpecimenBuilder());
return fixture;
}) { }
}
[Theory]
[AutoData]
public void Should_create_a_customer(Customer customer1, Customer customer2, SomethingElse something)
{
}
CompositeCustomization
to combine multiple customizations into one.public class CustomerWithNewOrdersAndOutstandingAcounts : CompositeCustomization
{
public CustomerWithNewOrdersAndOutstandingAcounts()
: base(new CustomerWithOrdersCustomization(), new CustomerWithOutstandingAcounts()) { }
}
27