2016-04-25 111 views
1

我想讓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類這樣

public class BaseUnitTestClass 
    { 
     internal static Fixture _fixture = new Fixture(); 

     public BaseUnitTestClass() 
     {    
      _fixture.Customizations.Add(new RandomEnumSequenceGenerator<TableType>()); 
     } 

我拉下來的源代碼,並注意到它遍歷composedBuilders,只有最後一個(在RandomEnumSequenceGenerator)滿足合同,它會創建一個TableType枚舉值,並嘗試將其轉換爲我試圖創建的實際類,該類會引發異常。

異常消息爲如下

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>(); 
+0

我們可以有例外的細節嗎? – Xiaoy312

+2

你不需要做values.Length - 1 btw,因爲Random.Next()的最大值是非包含的。 –

回答

2

你的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); 
    } 
} 

我還沒有試過編譯和測試這一點,所以你可能需要調整有點,但它應該證明你要點必須這樣做。

+0

當我運行這個t時,當enum(TableType)的請求進入時,t總是空的。轉換爲類型失敗。 – reggaeguitar

+1

嘗試'fixture.Customizations.Insert(0,new RandomEnumSequenceGenerator ())'。 –

+0

這樣做的竅門,非常感謝您的幫助 – reggaeguitar

2

這應該修復類型轉換異常,假設是罪魁禍首:

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]; 
    } 
} 
+0

引發異常的強制轉換是在AutoFixture源代碼中,這不能解決問題。謝謝你嘗試。 – reggaeguitar

+0

你能提供異常消息和堆棧跟蹤嗎? – Xiaoy312