2016-09-20 69 views
2

我第一次使用SpecFlow爲我的項目編寫測試,並遇到一個小問題。如何在SpecFlow中使用table.CreateSet <>(myClass)()生成缺失值?

我隔壁班:

public class FancyName 
{ 
    [DataMember] 
    public Guid Guid { get; set; } 

    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public List <Country> Countries { get; set; } 
} 

我想生成這個類中使用SpecFlow助手我的測試。

下面是場景的一部分:

[...] 
When i add some names 
    | Name | Countries | 
    | UK | 1   | 
    | US | 2   | 
[...] 

我嘗試解析在步驟的定義是這樣的:

[When(@"I add some names")] 
public void AddNames(Table table) 
{ 
    var names = table.CreateSet<FancyName>(); 
    [...] 
} 

而且我遇到了兩個問題:

  1. 我不通過Guid,因爲想要生成它就像Guid.NewGuid()那樣創建的對象包含null
  2. 我通過國家排序,但我需要創建List<Country>()

我曾嘗試迭代表格並手動創建FancyName對象,但據我所知它不是SpecFlow的方式。我試圖查看文檔,找到合適的解決方案並不幸運。

可能有人知道解決這個問題的好方法嗎? 在此先感謝。

+0

國家類型是怎麼樣的? 最後應該怎麼看你的類型的實例? –

回答

2

Table.CreateSet<>無法施展魔法。它不知道它應該爲你的對象創建一個新的Guid,或者它應該創建一個包含2個國家的列表。我想你必須自己創建這個對象。

來解決它的最好方法是使用[StepArgumentTransformation]

是這樣的:

[StepArgumentTransformation] 
public List<FancyName> TransformToFancyName(Table table) 
{ 
    //create the list from the table contents 
} 

[When(@"I add some names")] 
public void AddNames(List<FancyName> names) 
{ 
    .. use your FancyNames here 
} 

specflow會打電話給你的StepArgumentTransformation對於具有的List<FancyName>參數作爲最後一個參數和任何步驟相應表中的功能

0

你可以考慮類似Nested Tables?,但根據這篇文章這是一個壞主意。它建議引入額外的步驟來填充複雜對象。

7

這裏的主要SpecFlow.Assist作者...

我同意@ sam持有人上面那Table.CreateSet<T>是不是魔術,也許這種轉換是一個更容易的解決方案在這種情況下。但是,Assist的確具有完成所要求的功能。 :)

我想解釋一下。我看到兩個問題呈現爲:

1)如何在每條記錄上設置Guid?

2)如何將字符串值轉換爲數組?(1),答案很簡單。你可以傳遞一個函數給CreateSet,告訴圖書館如何實例化你想創建的對象。既然你只是想設置的GUID,你可以做到這一點,像這樣:

table.CreateSet<FancyName>(() => new FancyName { Guid = Guid.NewGuid()}); 
    // or simpler, table.CreateSet(() => new FancyName { Guid = Guid.NewGuid()}); 

對於(2),你必須做一些更多的編程。您希望Assist知道如何將字符串轉換爲列表。要做到這一點,您必須創建一個「價值檢索器」並將其註冊到Assist。我可以用下面的代碼來做到這一點:

public class CountryRetriever : IValueRetriever 
{ 
    public bool CanRetrieve(KeyValuePair<string, string> keyValuePair, Type targetType, Type propertyType) 
    { 
     return propertyType.FullName.StartsWith("System.Collections.Generic.List`1[[SpecFlowExample.Country"); 
    } 

    public object Retrieve(KeyValuePair<string, string> keyValuePair, Type targetType, Type propertyType) 
    { 
     return keyValuePair.Value.Split(',') 
      .Select(x => new Country {Name = x}) 
      .ToList(); 
    } 
} 

[Binding] 
public class Steps 
{ 
    [BeforeTestRun] 
    public static void Setup() 
    { 
     TechTalk.SpecFlow.Assist.Service.Instance.RegisterValueRetriever(new CountryRetriever()); 
    } 

    [When(@"i add some names")] 
    public void WhenIAddSomeNames(Table table) 
    { 
     var things = table.CreateSet<FancyName>(() => new FancyName { Guid = Guid.NewGuid()}); 

    } 
} 

直接在這樣的列表指點,尤其是在使用一個字符串,是相當哈克,但是這個代碼不工作。

國家檢索器將宣佈它可以處理字符串轉換時遇到List<Country>類型。然後分割字符串並創建一個國家列表。

SpecFlow會針對大多數基本.Net類型啓動每個測試運行,但不包括您的List<Country>。爲了適應您的類型,您需要在每次測試運行前註冊您的新值檢索器。

相關問題