如何结合IApplyToTest与TestFixtureSource获取所有子测试?
解决NUnit中TestFixtureSource下IApplyToTest获取子测试为空的问题
问题场景
自定义实现IApplyToTest接口的MyAttribute特性,与[TestFixture]配合使用时,ApplyToTest方法能收到TestFixture实例,通过test.Tests可正常递归获取所有子测试;但切换为[TestFixtureSource]时,方法收到的是ParameterizedFixtureSuite实例,其Tests属性为空,无法获取子测试。
解决方案
方案1:改用IApplyToSuite接口
ParameterizedFixtureSuite属于Suite类型,IApplyToTest会在其子测试生成前被调用,导致Tests为空。换成IApplyToSuite接口后,方法会在Suite的所有子测试生成完成后执行,此时可完整获取子测试集合:
[AttributeUsage(AttributeTargets.Class)] sealed class MyAttribute : NUnitAttribute, IApplyToSuite { public void ApplyToSuite(TestSuite suite) { // 递归遍历所有子测试 foreach (var test in suite.Tests) { // 处理当前测试逻辑 if (test is TestSuite childSuite) { ApplyToSuite(childSuite); } } } }
方案2:通过事件延迟获取子测试(保留IApplyToTest)
若必须使用IApplyToTest,可监听测试的TestCreated事件,在子测试动态创建完成后再处理:
[AttributeUsage(AttributeTargets.Class)] sealed class MyAttribute : NUnitAttribute, IApplyToTest { public void ApplyToTest(Test test) { if (test is ParameterizedFixtureSuite suite) { suite.TestCreated += Suite_TestCreated; } else { // 原TestFixture场景的处理逻辑 ProcessTest(test); } } private void Suite_TestCreated(object sender, TestEventArgs e) { ProcessTest(e.Test); // 递归监听孙子测试的创建事件 if (e.Test is TestSuite childSuite) { childSuite.TestCreated += Suite_TestCreated; } } private void ProcessTest(Test test) { // 自定义测试处理逻辑 } }
原因说明
NUnit的执行流程中,TestFixtureSource会先创建ParameterizedFixtureSuite作为容器,后续才动态生成对应的TestFixture实例作为子测试。IApplyToTest在容器创建后立即执行,此时子测试尚未生成,因此Tests为空;而IApplyToSuite会等待Suite的所有子测试创建完成后再触发调用,能拿到完整的子测试列表。
内容的提问来源于stack exchange,提问作者Marco Eckstein
相关产品推荐
相关产品推荐

