【问题标题】:NUnit 3.x - TestCaseSource for descendant test classesNUnit 3.x - 后代测试类的 TestCaseSource
【发布时间】:2017-07-26 06:08:48
【问题描述】:

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

public abstract class GetAllRouteTests<TModel, TModule>
{
  [Test]
  public void HasModels_ReturnsPagedModel()
  {
     // Implemented test
  }
}

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

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

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 实现了许多测试,而不仅仅是显示的那个。
  • 在一个测试中遍历所有路由将“隐藏”所涵盖的内容,因此希望避免这种情况。

【问题讨论】:

    标签: c# unit-testing nunit


    【解决方案1】:

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

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

    【讨论】:

    • 正如我们所愿。 :-) 此外,将数据放在单独的类中比将其放入测试类要干净得多。
    • 哦,整洁 - 没有比框架的主要开发人员的认可更好:)
    • 那么是否需要在实现的夹具上定义 [TestCaseSource*] 属性?有没有办法在父夹具上定义它,以便可以在基/父夹具中实现通用测试?
    • @Charlie 有没有办法将TestCaseSource 放在父抽象夹具中,而不必在每个继承它的类中发送垃圾邮件?
    • @Vedran 该属性显然必须出现在每个测试中。但数据本身可能位于基类中,使用继承夹具可访问的字段、属性或方法。它也可能在一个不相关的类中,只要您在 TestCaseSourceAttribute 构造函数中指定类型。
    猜你喜欢
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多