关于 c#:NUnit 3.x – 后代测试类的 TestCaseSource

NUnit 3.x - TestCaseSource for descendant test classes

我目前有一组单元测试,它们对于许多 Rest API 端点都是一致的。假设类是这样定义的。

1
2
3
4
5
6
7
8
public abstract class GetAllRouteTests<TModel, TModule>
{
  [Test]
  public void HasModels_ReturnsPagedModel()
  {
     // Implemented test
  }
}

实现的测试夹具看起来像:

1
2
[TestFixture(Category ="/api/route-to-test")]
public GetAllTheThings : GetAllRouteTests<TheThing, ModuleTheThings> { }

这使我能够在所有 GET all/list 路由上运行许多常见测试。这也意味着我有直接链接到正在测试的模块的类,以及 Resharper / Visual Studio / CI"正常工作"中的测试和代码之间的链接。

挑战在于,有些路由需要查询参数才能通过路由代码测试其他路径;

例如/api/route-to-test?category=big.

由于 [TestCaseSource] 需要静态字段、属性或方法,因此似乎没有很好的方法来覆盖要传递的查询字符串列表。我想出的最接近的东西似乎是一个黑客。即:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class GetAllRouteTests<TModel, TModule>
{
  [TestCaseSource("StaticToDefineLater")]
  public void HasModels_ReturnsPagedModel(dynamic args)
  {
     // Implemented test
  }
}

[TestFixture(Category ="/api/route-to-test")]
public GetAllTheThings : GetAllRouteTests<TheThing, ModuleTheThings>
{
    static IEnumerable<dynamic> StaticToDefineLater()
    {
       // yield return all the query things
    }
}

这是因为静态方法是为实现的测试类定义的,并且由 NUnit 找到。巨大的黑客。对于使用抽象类的其他人来说也是有问题的,因为他们需要"知道"将"StaticToDefineLater"实现为静态的东西。

我正在寻找一种更好的方法来实现这一目标。似乎在 NUnit 3.x 中删除了非静态 TestCaseSource 源,所以它已经出局了。

提前致谢。

注释:

  • GetAllRouteTests<> 实现了许多测试,而不仅仅是显示的那个。
  • 在一个测试中遍历所有路线将"隐藏"所涵盖的内容,因此希望避免这种情况。

我解决类似问题的方法是拥有一个实现 IEnumerable(NUnit 的另一个可接受的源)的基源类,考虑这种设计是否适合您的用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// in the parent fixture...
public abstract class TestCases : IEnumerable
{
    protected abstract List<List<object>> Cases { get; }

    public IEnumerator GetEnumerator()
    {
        return Cases.GetEnumerator();
    }
}

// in tests
private class TestCasesForTestFoobar : TestCases
{
    protected override List<List<object>> Cases => /* sets of args */
}

[TestCaseSource(typeof(TestCasesForTestFoobar))]
public void TestFoobar(List<object> args)
{
    // implemented test
}