如何在NUnit 3中改写NUnit 2含返回对象的ExpectedException测试?
把NUnit 2带
ExpectedException的返回值测试迁移到NUnit 3 别发愁,我来帮你把NUnit 2里那种带ExpectedException属性且有返回对象的测试改成NUnit 3的标准写法。核心就是抛弃旧的ExpectedException属性,改用NUnit 3推荐的断言式异常捕获,这样不仅更灵活,还能做更细致的异常验证。
先看你原来NUnit 2的测试大概长这样
假设你的测试代码是类似下面的结构:
[Test] [ExpectedException(typeof(InvalidOperationException))] public MyObject TestMethodThatThrows() { // 触发异常的业务逻辑 throw new InvalidOperationException("参数不合法"); // 下面的返回语句其实永远不会执行,只是满足方法签名 return new MyObject(); }
NUnit 3的两种改写方式
方式1:同步方法用Assert.Throws<T>
NUnit 3里用Assert.Throws<T>来精准捕获指定类型的异常,它还会返回异常对象,方便你验证异常的细节(比如消息、内部异常)。测试方法通常改成void,因为抛出异常后返回值根本不会被用到:
[Test] public void TestMethodThatThrows() { // 用Assert.Throws包裹会抛出异常的代码块 var thrownException = Assert.Throws<InvalidOperationException>(() => { // 这里调用你原来的业务方法(就是会抛出异常、返回MyObject的那个方法) var result = MyBusinessMethod(); }); // 可选:验证异常的具体消息,替代NUnit 2里的ExpectedMessage参数 Assert.That(thrownException.Message, Is.EqualTo("参数不合法")); } // 假设被测试的业务方法是这样的 private MyObject MyBusinessMethod() { throw new InvalidOperationException("参数不合法"); return new MyObject(); }
方式2:异步方法用Assert.ThrowsAsync<T>
如果你的测试是异步方法(返回Task或Task<T>),就用对应的异步版本:
[Test] public async Task TestAsyncMethodThatThrows() { var thrownException = await Assert.ThrowsAsync<InvalidOperationException>(async () => { var result = await MyAsyncBusinessMethod(); }); Assert.That(thrownException.Message, Is.EqualTo("异步操作参数错误")); }
为什么要这么改?
NUnit 3弃用ExpectedException是因为它有几个明显的局限性:
- 无法精准控制哪一行代码抛出异常——如果测试方法里有多个可能抛异常的步骤,
ExpectedException会误判 - 很难验证异常的额外信息(比如消息、内部异常),只能判断类型
- 带返回值的测试方法里,返回语句完全是冗余的,因为抛出异常后根本不会执行
而Assert.Throws系列方法解决了这些问题,让测试逻辑更清晰、更严谨。
内容的提问来源于stack exchange,提问作者Jake Manet
相关产品推荐
相关产品推荐

