How do I create a base test class in Xunit to test interface implementations?
Asked Answered
A

1

2

I am writing a test suite for a class library using C# and XUnit. In the library are a number of classes that implement an interface. I could simply copy-paste the same tests for the interface implementation into each test class but I was wondering if there is a neater solution using some test base class which can be inherited from and run automatically without calling each method in turn in each test class.

This article on codeproject demonstrates how it would be done in mstest using an abstract base class marked with TestClass. A summary is given below. However I cannot figure out if there is an equivalent using xunit. Does anyone know how to approach this? The xunit docs say there is no equivalent to TestClass in mstest.

Interface

public interface IDoSomething
{
  int SearchString(string stringToSearch, string pattern);
}

One of many classes implementing interface

public class ThisDoesSomething : IDoSomething
{
  public int SearchString(string stringToSearch, string pattern);
  {
    // implementation
  }
}

Interface Test base class

[TestClass]
public abstract class IDoSomethingTestBase
{
  public abstract IDoSomething GetDoSomethingInstance();

  [TestMethod]
  public void BasicTest()
  {
    IDoSomething ids = GetDoSomethingInstance();
    Assert.AreEqual("a_string", ids.SearchString("a_string", ".*");
  }
}

Test class that tests the class implementing interface

[TestClass]
public class ThisDoesSomething_Tests : IDoSomethingTestBase
{
  public override IDoSomething GetDoSomethingInstance()
  {
    return new ThisDoesSomething();
  }
}
Acidulent answered 14/2, 2020 at 0:55 Comment(0)
S
3

Works exactly the same way...

public abstract class IDoSomethingTestBase
{
  protected readonly IDoSomething InstanceUnderTest;

  protected IDoSomethingTestBase(IDoSomething instanceUnderTest){
    InstanceUnderTest = instanceUnderTest;
  }

  [Fact]
  public void BasicTest()
  {
    Assert.AreEqual("a_string", InstanceUnderTest.SearchString("a_string", ".*");
  }
}

Actual test class:

public class ThisDoesSomething_Tests : IDoSomethingTestBase
{
  public ThisDoesSomething_Tests(): base(new ThisDoesSomething()) { }
}
Solfeggio answered 14/2, 2020 at 9:31 Comment(2)
Thank you, but how do you then debug the test against an instance class? The test method is in the base class.Acidulent
In Visual Studio they will show up as separate test classes (the base class itself won't show) in the test explorer (right click a test and choose debug). In VS Code there is a handy plugin which does the same thing: marketplace.visualstudio.com/…Solfeggio

© 2022 - 2024 — McMap. All rights reserved.