Reputation: 1017
We use AutoFixture for test data generation, one of the scenarios requires us to provide fixed data, so we can test the method below.
public enum OrderState { Initial = 0, State1 = 1, State2 = 2, State3 = 3 };
public record Order(Guid Id, string Reference, OrderState State);
public static class Filter
{
public static IEnumerable<Order> ByState(IEnumerable<Order> orders, OrderState state)
{
return orders.Where(order => order.State == state);
}
}
Test
[Fact]
public void Returns_only_orders_with_initial_state()
{
// Arrange
var fixture = new Fixture();
var order1 = fixture.Build(o => o.State, OrderState.Initial).Create();
var allOrders = new[]
{
fixture.Build(o => o.State, OrderState.State1).Create(),
fixture.Build(o => o.State, OrderState.State2).Create(),
fixture.Build(o => o.State, OrderState.State3).Create(),
order1
};
// Act
var actual = new Filter().ByState(allOrders, OrderState.Initial);
// Assert
actual.Should().BeEquivalentTo(new[] { order1 });
}
Test fails because AutoFixture can not write to readonly properties - I understand that.
How can I create an instance with fixed value for the State
property, but still use "random" values for other properties?
Upvotes: 1
Views: 455
Reputation: 734
You can achieve this using AutoFixture's SpecimenBuilder
facility.
An example of his can be found in this post
A demonstration for your use case:
using AutoFixture.Kernel;
using System.Reflection;
namespace Example
{
public enum OrderState { Initial = 0, State1 = 1, State2 = 2, State3 = 3 };
public record Order(Guid Id, string Reference, OrderState State);
public class OrderStateArg : ISpecimenBuilder
{
private readonly OrderState _state;
public OrderStateArg(OrderState state)
{
_state = state;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi == null)
{
return new NoSpecimen();
}
if (pi.Member.DeclaringType != typeof(Order) ||
pi.ParameterType != typeof(OrderState) ||
pi.Name != "State")
{
return new NoSpecimen();
}
return _state;
}
}
public static class Filter
{
public static IEnumerable<Order> ByState(IEnumerable<Order> orders, OrderState state)
{
return orders.Where(order => order.State == state);
}
}
public class Class1
{
[Fact]
public void Returns_only_orders_with_initial_state()
{
var fixture = new Fixture();
fixture.Customizations.Add(new OrderStateArg(OrderState.Initial));
var order1 = fixture.Create<Order>();
fixture.Customizations.Clear();
var allOrders = new Order[]
{
fixture.Create<Order>(),
fixture.Create<Order>(),
fixture.Create<Order>(),
order1
};
// Act
// Note on your original code, Filter is a static class
// so calling its methods do not require the new keyword.
var actual = Filter.ByState(allOrders, OrderState.Initial);
// Assert
actual.Should().BeEquivalentTo(new[] { order1 });
}
}
}
Upvotes: 0