如何使用TestCase测试同一方法抛出的不同类型异常
优化方案
你可以直接将期望的异常类型作为TestCase的额外入参,配合NUnit内置的Assert.Throws方法即可实现需求,完全不需要手动写try catch,也不需要拆分测试用例,写法更简洁也更符合单元测试的AAA规范:
[TestCase(0, typeof(KeyNotFoundException))] [TestCase(2, typeof(AmbiguousMatchException))] public void ThrowIfNotInConfig_GIVEN_NotASingleEndpointInConfig_THEN_ThrowError(int configOccurrences, Type expectedExceptionType) { // Arrange const string endpointRef = "ABC"; var config = _validConfig; config.Endpoints.RemoveAll(x => x.Ref == endpointRef); config.Endpoints .AddRange(Enumerable.Range(0, configOccurrences) .Select(x => new MiraklEndpointConfig { Ref = endpointRef }) ); _config.Setup(c => c.Value).Returns(config); var service = new URLThrottlingService(_mockLogger.Object, _config.Object); // Act & Assert Assert.Throws(expectedExceptionType, () => service.IsOKToCallEndpoint(endpointRef)); }
补充说明
- 旧版NUnit的
ExpectedException特性已经在NUnit 3之后被官方弃用,原因是它会校验整个测试方法生命周期内抛出的对应异常,校验范围过大容易出现误判。而Assert.Throws只会校验传入委托执行时抛出的异常,精准度更高。 - 如果需要同时校验异常的消息内容,可以捕获
Assert.Throws返回的异常对象做二次校验:
var thrownException = Assert.Throws(expectedExceptionType, () => service.IsOKToCallEndpoint(endpointRef)); Assert.That(thrownException.Message, Does.Contain(endpointRef));
- 如果你项目中引入了FluentAssertions类库,断言写法可以更符合阅读习惯:
service.Invoking(s => s.IsOKToCallEndpoint(endpointRef)) .Should() .Throw(expectedExceptionType);
内容的提问来源于stack exchange,提问作者Red
相关产品推荐
相关产品推荐

