2016-08-16 65 views
1

我試圖建立一些測試用例爲我的測試:與NUnit的TestCaseData參數個數錯誤

public IEnumerable<TestCaseData> size_tests() 
{ 
    yield return new TestCaseData(new string[] { "XS", "XL", "M" }) 
     .Returns(new SortedVariantAttributeModel { 
      Values = new string[] { "XS", "M", "XL" }, 
      PrimaryValue = "XS" 
     }); 
} 

[Test, TestCaseSource("size_tests")] 
public SortedVariantAttributeModel Should_map_SortedVariantAttributes(string[] sizes) 
{ 
    // ... 
} 

當我嘗試運行這個測試,我得到:

測試失敗 - Should_map_SortedVariantAttributes( 「XS」, 「XL」, 「M」)

消息:參數數目錯誤提供

由錯誤判斷它似乎解開數組並嘗試將其應用於測試函數,但這當然會導致問題。我該如何解決這個問題?

+0

您使用的是什麼版本的NUnit? –

回答

2

爲了得到這個工作,你需要將參數包裝在這樣的數組中,new[] { new string[] { "XS", "XL", "M" } }。這導致NUnit將字符串數組視爲方法的第一個參數,而不是一系列字符串參數。

我相信你正在使用NUnit 2.x,因爲你的數據源不是靜態的。我簡化了代碼並在NUnit 2.6.4和3.4.1中測試瞭解決方法。

public static IEnumerable<TestCaseData> Data() 
{ 
    yield return new TestCaseData(new[] { new string[] { "XS", "XL", "M" } }); 
    yield return new TestCaseData(new[] { new string[] { "S", "M", "XXL", "L" } }); 
} 

[TestCaseSource(nameof(Data))] 
public void TestStringArrayArguments(string[] sizes) 
{ 
    Assert.That(sizes.Length, Is.GreaterThan(1)); 
} 
+0

不錯;這是C#的新名稱(...)'特性有用的地方之一。還有另一種強制正確重載的方法,那就是'yield返回新的TestCaseData((object)(new string [] {「XS」,「XL」,「M」}));'。構造函數有幾個重載,並且有'params'的重載有兩種方式。 –

+0

這是一個更好的解決方法,謝謝。 –

+0

我最終在單獨的答案中提供了詳細信息。 –

2

相關的實例構造具有以下重載:

public TestCaseData(params object[] args) { /* ... */ } //A 

public TestCaseData(object arg) { /* ... */ } //B 

public TestCaseData(object arg1, object arg2) { /* ... */ } //C 

public TestCaseData(object arg1, object arg2, object arg3) { /* ... */ } //D 

params過載可以通過兩種方式申請,無論是在正常形態,你給對象數組明確地在你的代碼,或者在展開形式中,您只需使用逗號指定一組對象(零個或多個)並且編譯器會爲您隱式生成該數組。請參閱§7.5.3.1C#規範中的適用函數成員

這樣做:

new TestCaseData(new string[] { "XS", "XL", "M" }) 

變得重要的是,C#(以及CLR)具有用於參考類型的數組可疑陣列協方差string是引用類型)。所以你的string[]「是」也是object[](在stringobject的事實上使用協方差)。

所以過載//A適用於正常形式。當正常形式適用時,不應考慮擴展形式的//A

過載//B在您的使用也適用,因爲string[]System.Array這是一個object

但是//A被認爲更具體(所有object[]object但現在反之亦然)並且優於//B。所以//A被用於其正常形式這不是你想要的。您的Should_map_SortedVariantAttributes需要一個參數(稱爲sizes),而不是三個。因此,這個問題。

一個好的解決方法是現在很容易:

new TestCaseData((object)(new string[] { "XS", "XL", "M" })) /* fixes your issue! */ 

現在我們有object類型的表達式。過載//A不再適用於其正常形式。所以這次檢查//A是否適用於它的擴展形式。

另外//B適用於此。

無論//A以展開形式//B會使你的代碼的工作,所以無論什麼C#重載決議在這種情況下選擇,我們很高興。

實際上,在這種情況下,C#規則(第7.5.3.2節)更喜歡使用擴展表格的常規形式,因此使用//B。這是一件好事,編譯器不必創建隱式長度爲1的對象數組。