XUnit.net MemberData Derived Theory

Using xUnit.net, is it possible that it Theory

has its own MemberData

from a derived class?

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
    }
}

      


In the above code, you receive the following error message:

System.NotSupportedException: The specified method is not supported.

+4


source to share


4 answers


As far as I know, this is not possible. MemberData

the data must be static

, so the data must come from its own class.



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

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

      

+4


source


You are correct in your answer. Posting this non-response in case it happens to spark the idea.

MemberData

can parameters be passed that might help depending on your specific scenario?



Also, the best you can try is to move the forwarder:

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);
}

      

+1


source


Another way to do this (and a cleaner IMO) is to put your test scripts in their own classes and simply define each script as a separate MemberData attribute:

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
    }
}

      

+1


source


Another way is to "override" this. It will check the members by name and pick the correct one from the current class. The only thing the parser warns is that you must specify a member in the base class (which is considered an error by default), so you will have to disable this rule. If you try to specify this method in both classes - base and derived only base classes will be used. Not sure why the analyzer works like this, it might be a bug, but I saw this approach here or on github, I'm not sure, but it worked well for the old version of the analyzer.

Your example might look like:

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
    }
}

      

0


source







All Articles