2017-07-25 95 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