2017-07-25 45 views
0

聯數據我是很新,的xUnit和這裏的想什麼,我來實現:Lambda表達式中的xUnit

[Theory] 
[InlineData((Config y) => y.Param1)] 
[InlineData((Config y) => y.Param2)] 
public void HasConfiguration(Func<Config, string> item) 
{ 
    var configuration = serviceProvider.GetService<GenericConfig>(); 
    var x = item(configuration.Config1); // Config1 is of type Config 

    Assert.True(!string.IsNullOrEmpty(x));    
} 

基本上,我有一個GenericConfig對象包含配置等種類的配置,但我需要檢查每個參數是否有效。由於它們都是字符串,我想簡化使用[InlineData]屬性,而不是寫N等於測試。

不幸的是,我得到的錯誤是「無法將lambda表達式轉換爲類型'object []',因爲它不是委託類型」,這非常清楚。

你有什麼想法來解決這個問題嗎?

回答

2

其實,我能夠找到一個解決方案這是一個有點比Iqon提供一個更好的(謝謝!)。

顯然,InlineData屬性只支持原始數據類型。如果您需要更復雜的類型,則可以使用MemberData屬性爲單元測試提供來自定製數據提供者的數據。

以下是我解決了這個問題:

public class ConfigTestCase 
{ 
    public static readonly IReadOnlyDictionary<string, Func<Config, string>> testCases = new Dictionary<string, Func<Config, string>> 
    { 
     { nameof(Config.Param1), (Config x) => x.Param1 }, 
     { nameof(Config.Param2), (Config x) => x.Param2 } 
    } 
    .ToImmutableDictionary(); 

    public static IEnumerable<object[]> TestCases 
    { 
     get 
     { 
      var items = new List<object[]>(); 

      foreach (var item in testCases) 
       items.Add(new object[] { item.Key }); 

      return items; 
     } 
    } 
} 

而這裏的測試方法:

[Theory] 
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))] 
public void Test(string currentField) 
{ 
    var func = ConfigTestCase.testCases.FirstOrDefault(x => x.Key == currentField).Value; 
    var config = serviceProvider.GetService<GenericConfig>(); 
    var result = func(config.Config1); 

    Assert.True(!string.IsNullOrEmpty(result)); 
} 

我可能會拿出一些好一點或清潔劑,但現在它的工作原理和該代碼不重複。

0

奇怪的代表是沒有對象,但Action s或Func s是。要做到這一點,你必須將lambda轉換爲這種類型之一。

object o = (Func<Config, string>)((Config y) => y.Param1) 

但是這樣做,你的表情不再是恆定的。所以這會阻止在Attribute中的使用。

沒有辦法將lambda作爲屬性傳遞。

一個可能的解決方案是使用函數調用,而不是屬性。不漂亮,但能解決你的問題,而無需重複代碼:

private void HasConfiguration(Func<Config, string> item) 
{ 
    var configuration = serviceProvider.GetService<GenericConfig>(); 
    var x = item(configuration.Config1); // Config1 is of type Config 

    Assert.True(!string.IsNullOrEmpty(x));    
} 

[Theory] 
public Test1() 
{ 
    HasConfiguration((Config y) => y.Param1); 
}  

[Theory] 
public Test2() 
{ 
    HasConfiguration((Config y) => y.Param2); 
} 
2

除已發佈的答案。通過直接生成lambda表達式可以簡化測試用例。

public class ConfigTestDataProvider 
{ 
    public static IEnumerable<object[]> TestCases 
    { 
     get 
     { 
      yield return new object [] { (Func<Config, object>)((x) => x.Param1) }; 
      yield return new object [] { (Func<Config, object>)((x) => x.Param2) }; 
     } 
    } 
} 

該測試ConfigTestDataProvider可以直接注入lambda表達式。

[Theory] 
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))] 
public void Test(Func<Config, object> func) 
{ 
    var config = serviceProvider.GetService<GenericConfig>(); 
    var result = func(config.Config1); 

    Assert.True(!string.IsNullOrEmpty(result)); 
} 
+0

雖然它似乎是一個更好的解決方案,但我不太喜歡它,因爲它會在測試瀏覽器中顯示爲單個測試。我很樂意看到所有必需的參數(如我在提供的答案中)。不管怎樣,謝謝你! – xTuMiOx

+0

真的,這看起來像是測試瀏覽器中的一個bug。 – Iqon