NUnit迁移xUnit实现多级集合Fixture 避免初始化逻辑重复执行
问题解答
错误原因
你当前的实现思路存在偏差,xUnit 原生不支持集合Fixture之间的依赖注入:集合Fixture的设计目标是给测试类提供全局共享的初始化资源,仅会被注入到标记了对应[Collection]属性的测试类中,不会被注入到另一个集合Fixture的构造函数中,这就是你遇到依赖解析报错的直接原因。
直接继承基类的执行逻辑
如果直接将初始化逻辑写在基类的实例构造函数中,确实会出现重复执行的问题:xUnit 运行时会为每个测试方法单独创建一个测试类实例,因此每个测试方法执行时都会触发一次基类构造函数的逻辑。
如果将初始化逻辑写在基类的静态构造函数中,则不会重复执行:静态构造函数在整个测试进程的生命周期内仅会执行一次,不过该方案需要注意多线程并行测试下的共享资源线程安全问题。
多层初始化仅执行一次的实现方案
方案1:合并集合Fixture逻辑(全局仅执行一次)
直接把两层初始化逻辑按顺序整合到同一个集合Fixture中,即可保证全局仅执行一次:
// 集合Fixture定义,全局仅初始化一次 public sealed class ControllerCollectionFixture { public ICacheManagerFactory CacheManagerFactory; public ControllerCollectionFixture() { // 原TestBase的初始化逻辑 // Setup code // 原ControllerTestBase的初始化逻辑 CacheManagerFactory.SomeSetup(); } } // 定义集合 [CollectionDefinition("ControllerTestCollection")] public class ControllerCollection : ICollectionFixture<ControllerCollectionFixture> { } // 测试基类,所有需要该初始化逻辑的测试类继承该基类即可 [Collection("ControllerTestCollection")] public class ControllerTestBase { protected ControllerCollectionFixture Fixture { get; } public ControllerTestBase(ControllerCollectionFixture fixture) { Fixture = fixture; } }
方案2:链式类Fixture继承(每个测试类仅执行一次)
如果不需要全局共享初始化资源,仅需要同一个测试类下的所有测试方法共享一次初始化,可以用类Fixture的继承实现:
// 底层 Fixture public class BaseFixture { public ICacheManagerFactory CacheManagerFactory { get; } public BaseFixture() { // 原TestBase初始化逻辑 } } // 上层 Fixture 继承底层 Fixture public class ControllerFixture : BaseFixture { public ControllerFixture() { // 原ControllerTestBase初始化逻辑 CacheManagerFactory.SomeSetup(); } } // 测试基类 public class ControllerTestBase : IClassFixture<ControllerFixture> { protected ControllerFixture Fixture { get; } public ControllerTestBase(ControllerFixture fixture) { Fixture = fixture; } }
内容的提问来源于stack exchange,提问作者JaamieT
相关产品推荐
相关产品推荐

