Lambda 表达式作为 xUnit 中的内联数据

xTu*_*iOx 7 .net c# unit-testing xunit

我对 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));            
}
Run Code Online (Sandbox Code Playgroud)

基本上,我有一个GenericConfig对象,其中包含Config和其他类型的配置,但我需要检查每个参数是否有效。由于它们都是字符串,我想简化使用[InlineData]属性而不是编写 N 等于测试。

不幸的是,我得到的错误是“无法将 lambda 表达式转换为类型 'object[]' 因为它不是委托类型”,这非常清楚。

您对如何克服这个问题有任何想法吗?

Iqo*_*qon 8

除了已经发布的答案。可以通过直接生成 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) };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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));
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然它看起来是一个更好的解决方案,但我不太喜欢它,因为它会在测试资源管理器中显示为单个测试。我很想看到所有必需的参数(如我提供的答案)。还是很感谢你! (3认同)

xTu*_*iOx 7

实际上,我找到了一个比 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是测试方法:

[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));
}
Run Code Online (Sandbox Code Playgroud)

我可能会想出更好或更简洁的东西,但现在它可以工作并且代码没有重复。