随机枚举生成
Random enum generation
我希望 AutoFixture 在我尝试创建的类型中包含枚举时使用枚举的随机值。与此基本相同 https://github.com/AutoFixture/AutoFixture/issues/360 但用于枚举。
我尝试了以下方法,但 AutoFixture 尝试创建枚举而不是请求的类型,但无法转换它。
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private Array _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T));
}
public object Create(object request, ISpecimenContext context)
{
var index = _random.Next(0, _values.Length - 1);
return _values.GetValue(index);
}
}
然后我在我的 BaseUnitTest class 中像这样使用它
public class BaseUnitTestClass
{
internal static Fixture _fixture = new Fixture();
public BaseUnitTestClass()
{
_fixture.Customizations.Add(new RandomEnumSequenceGenerator<TableType>());
}
我拉下了源代码,注意到它循环遍历了 composedBuilder,只有最后一个(RandomEnumSequenceGenerator)满足了约定,然后它创建了一个 TableType 枚举值并尝试将其转换为实际的 class 我正在尝试创建会引发异常的内容。
异常信息如下
at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context, T seed)
at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context)
at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenBuilder builder)
at UnitTests.Unit.BaseUnitTestClass.GetRandomT in mypath\BaseUnitTestClass.cs:line 49
Result Message: System.InvalidCastException : Unable to cast object of type 'MyNamespace.TableType' to type 'MyNameSpace.AssumptionChangeCriteria'.
AssumptionChangeCriteria 有一个 属性 类型 TableType
,它是一个枚举。
其中GetRandom<T>
如下
return _fixture.Create<T>();
这应该可以修复类型转换异常,假设这是罪魁祸首:
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private T[] _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T))
.Cast<T>()
.ToArray();
}
public object Create(object request, ISpecimenContext context)
{
var index = _random.Next(_values.Length);
return _values[index];
}
}
您的 RandomEnumSequenceGenerator<T>
版本不检查 request
,因此它只响应 任何 请求,即使它不是请求对于它自定义的类型。
最简单的修复可能是这样的:
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private Array _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T));
}
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || t != typeof(T))
return new NoSpecimen();
var index = _random.Next(0, _values.Length - 1);
return _values.GetValue(index);
}
}
我还没有尝试编译和测试它,所以您可能需要稍微调整一下,但它应该能说明您必须做的事情的要点。
修改了@mark-seemann的答案。请注意,Random.Next
的上限是独占的。
public class RandomEnumSequenceGenerator : ISpecimenBuilder
{
private static readonly Random Random = new Random();
public object Create(object request, ISpecimenContext context)
{
var seededRequest = request as SeededRequest;
var type = seededRequest?.Request as Type;
if (type == null || !type.IsEnum)
{
return new NoSpecimen();
}
var values = Enum.GetValues(type);
var index = Random.Next(values.Length);
return values.GetValue(index);
}
}
用法:
Fixture.Customizations.Add(new RandomEnumSequenceGenerator());
我希望 AutoFixture 在我尝试创建的类型中包含枚举时使用枚举的随机值。与此基本相同 https://github.com/AutoFixture/AutoFixture/issues/360 但用于枚举。
我尝试了以下方法,但 AutoFixture 尝试创建枚举而不是请求的类型,但无法转换它。
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private Array _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T));
}
public object Create(object request, ISpecimenContext context)
{
var index = _random.Next(0, _values.Length - 1);
return _values.GetValue(index);
}
}
然后我在我的 BaseUnitTest class 中像这样使用它
public class BaseUnitTestClass
{
internal static Fixture _fixture = new Fixture();
public BaseUnitTestClass()
{
_fixture.Customizations.Add(new RandomEnumSequenceGenerator<TableType>());
}
我拉下了源代码,注意到它循环遍历了 composedBuilder,只有最后一个(RandomEnumSequenceGenerator)满足了约定,然后它创建了一个 TableType 枚举值并尝试将其转换为实际的 class 我正在尝试创建会引发异常的内容。
异常信息如下
at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context, T seed) at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context) at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenBuilder builder) at UnitTests.Unit.BaseUnitTestClass.GetRandomT in mypath\BaseUnitTestClass.cs:line 49 Result Message: System.InvalidCastException : Unable to cast object of type 'MyNamespace.TableType' to type 'MyNameSpace.AssumptionChangeCriteria'.
AssumptionChangeCriteria 有一个 属性 类型 TableType
,它是一个枚举。
其中GetRandom<T>
如下
return _fixture.Create<T>();
这应该可以修复类型转换异常,假设这是罪魁祸首:
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private T[] _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T))
.Cast<T>()
.ToArray();
}
public object Create(object request, ISpecimenContext context)
{
var index = _random.Next(_values.Length);
return _values[index];
}
}
您的 RandomEnumSequenceGenerator<T>
版本不检查 request
,因此它只响应 任何 请求,即使它不是请求对于它自定义的类型。
最简单的修复可能是这样的:
public class RandomEnumSequenceGenerator<T> : ISpecimenBuilder where T : struct
{
private static Random _random = new Random();
private Array _values;
public RandomEnumSequenceGenerator()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum");
}
_values = Enum.GetValues(typeof(T));
}
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || t != typeof(T))
return new NoSpecimen();
var index = _random.Next(0, _values.Length - 1);
return _values.GetValue(index);
}
}
我还没有尝试编译和测试它,所以您可能需要稍微调整一下,但它应该能说明您必须做的事情的要点。
修改了@mark-seemann的答案。请注意,Random.Next
的上限是独占的。
public class RandomEnumSequenceGenerator : ISpecimenBuilder
{
private static readonly Random Random = new Random();
public object Create(object request, ISpecimenContext context)
{
var seededRequest = request as SeededRequest;
var type = seededRequest?.Request as Type;
if (type == null || !type.IsEnum)
{
return new NoSpecimen();
}
var values = Enum.GetValues(type);
var index = Random.Next(values.Length);
return values.GetValue(index);
}
}
用法:
Fixture.Customizations.Add(new RandomEnumSequenceGenerator());