xUnit.net MemberData 来自派生的理论 class

xUnit.net Theory where MemberData is from derived class

使用 xUnit.net,Theory 可以从派生的 class 派生出 MemberData 吗?

public abstract class BaseTest
{
    public abstract IEnumerable<object[]> Data();

    [Theory]
    [MemberData(nameof(Data))]
    public void TestData(string expected, string actual)
    {
        // assert goes here
    }
}

public class ComplexTest : BaseTest
{
    public override IEnumerable<object[]> Data()
    {
        // data goes here
    }
}

以上代码导致以下错误消息:

System.NotSupportedException : Specified method is not supported.

据我所知,这是不可能的。 MemberData的数据要求是static,所以数据必须来源于它自己的class。

public static IEnumerable<object[]> Data()
{
    // data goes here
}

[Theory]
[MemberData(nameof(Data))]
public void TestData(string expected, string actual)
{
    // assert goes here
}

您的回答是正确的。发布这个非答案以防它碰巧激发出一个想法。

MemberData 可以传递参数,这可能对您的具体情况有所帮助?

除此之外,您可能做的最好的事情就是放置一个转发器:

public abstract class BaseTest
{
    protected void RunTest(string expected, string actual)
    {
        Assert.Equal(expected, actual);
    }
}

public class ComplexTest : BaseTest
{
    static IEnumerable<object[]> Data() = 
    {
        { "a", "a" }
    }

    [Theory, MemberData(nameof(Data))]
    void TestData(expected, actual) => base.RunTest(expected, actual);
}

另一种方法(和 IMO 清洁器)是将您的测试场景放在自己特定的 类 中,并将每个场景集定义为单独的 MemberData 属性:

public class BaseTest
{
    [Theory]
    [MemberData(nameof(TestScenarios1.Data), MemberType = typeof(TestScenarios1)]
    [MemberData(nameof(TestScenarios1.MoreData), MemberType = typeof(TestScenarios1)]
    [MemberData(nameof(TestScenarios2.DifferentData), MemberType = typeof(TestScenarios2)]
    public void TestData(string expected, string actual)
    {
        // assert goes here
    }
}

public class TestScenarios1
{
    public static IEnumerable<object[]> Data()
    {
        // data goes here
    }

    public static IEnumerable<object[]> MoreData()
    {
        // data goes here
    }
}

public class TestScenarios2
{
    public static IEnumerable<object[]> DifferentData()
    {
        // data goes here
    }
}

另一种方法是仅将 MemberData 添加到派生 class。 它将按名称检查成员并从当前 class 中取出正确的成员。 分析器唯一警告您必须在 base class 中指定成员(默认情况下被视为错误),因此您必须禁用此规则。如果您尝试在 classes 中指定此方法 - 将仅使用基础和派生基础 classes。 xunit github中描述的关于分析器的问题:https://github.com/xunit/xunit/issues/1243

您的示例可能如下所示:

public abstract class BaseTest
{
    [Theory]
#pragma warning disable xUnit1015 // MemberData must reference an existing member
    [MemberData(nameof(Data))]
#pragma warning restore xUnit1015 // MemberData must reference an existing member
    public void TestData(string expected, string actual)
    {
        // assert goes here
    }
}

public class ComplexTest : BaseTest
{
    public static IEnumerable<object[]> Data()
    {
        return data;
        // data goes here
    }
}