GlacialMan
GlacialMan

Reputation: 597

xUnit Abstract Test Class with virtual test methods with parameters

I just started with Unit Testing and I'm using xUnit framework. I have an AbstractTest class that defines some abstract test methods which I'll use in every test class. The problem is in the static field - InsertData. MemberData in this case InsertData must be static. I can't assign some value to InsertData in the inherited class (TestClass) because I got the error before debugger touch both constructors.

public abstract class AbstractTest<TModel> where TModel : class
{
   public IRepository<TModel> repo;
   public static IEnumerable<object[]> InsertData;

   [Theory]
   [MemberData(nameof(InsertData))]
   public virtual void AbsTestInsert(TModel model)
   {
       try
       {
           repo.AddUpdate(model);
           Assert.True(true);
       }
       catch (Exception ex)
       {
           Assert.True(false, ex.Message);
       }
   }
}

public class TestClass : AbstractTest<TestModel>
{
    public TestClass()
    {
        repo = TestRepository();
    }
}

Because I inherit the AbstractTest class I'll have the test. Test class

I can't find a solution to InsertData remain static but to override its value in the inherited class.

I have idea with something like this:

public static IEnumerable<object[]> InsertData() => Data;
public abstract/virtual IEnumerable<object[]> Data()
{
    return ...;
}

But to do this Data also must me static...

Upvotes: 5

Views: 3138

Answers (1)

Brad Wilson
Brad Wilson

Reputation: 70696

The requirement for theory data to come from a static source is a hard requirement with no workaround. However, there is no requirement that the data be defined on the abstract class at all. You can do this:

public abstract class AbstractTest<TModel> where TModel : class
{
   public IRepository<TModel> repo;

   [Theory]
   [MemberData("InsertData")]
   public virtual void AbsTestInsert(TModel model)
   {
       try
       {
           repo.AddUpdate(model);
           Assert.True(true);
       }
       catch (Exception ex)
       {
           Assert.True(false, ex.Message);
       }
   }
}

public class TestClass : AbstractTest<TestModel>
{
    public static IEnumerable<object[]> InsertData;

    public TestClass()
    {
        repo = TestRepository();
    }
}

You define the data using the same name on each implementing class. It's not virtual/abstract, it's just lining things up by name.

Upvotes: 7

Related Questions