为何Assert.Multiple会“记住”已捕获的断言失败?
问题
为什么第一个代码块中已捕获的AssertionException会被Assert.Multiple再次捕获?直接调用Assert.True(true)不会抛出异常,当前使用.NET 6.0。
示例代码
using NUnit.Framework; namespace Sandbox { public class Program { public static void Main(string[] args) { try { Assert.Fail("Fail!"); } catch (Exception e) { Console.WriteLine("Expected exception"); } try { Assert.Multiple(() => { Assert.True(true); }); } catch (Exception e) { Console.WriteLine("Unexpected exception: " + e.Message); } } } }
运行输出
Expected exception
Unexpected exception: Fail!
原因解析
这是因为NUnit的断言机制依赖线程本地的断言上下文跟踪断言结果。第一个Assert.Fail抛出的异常虽然被捕获,但NUnit内部的线程上下文并未重置,依然保留着这次失败的断言记录。
当调用Assert.Multiple时,它会先检查当前线程上下文里的所有历史断言结果,一旦发现未清理的失败记录,就会抛出包含该失败信息的异常。而直接调用Assert.True(true)时,单个断言只会验证自身逻辑是否通过,不会检查上下文里的历史记录,因此不会触发异常。
如果是在NUnit测试类的测试方法中执行这段逻辑,NUnit会在每个测试方法执行前后自动重置线程上下文,就不会出现这种问题。而在控制台程序的Main方法中,没有NUnit的测试生命周期管理,上下文不会自动重置,才会出现这种“旧异常被复用”的情况。
内容的提问来源于stack exchange,提问作者Glorfindel
相关产品推荐
相关产品推荐

