NUnit Throws约束如何断言异常内列表对象的属性值
NUnit自定义异常集合属性断言正确写法
问题说明
现有自定义异常类,包含存储多条校验错误的列表属性,类定义如下:
public class MyExceptions : Exception { public List<MyValidationError> ValidationErrors { get; set; } } public class MyValidationError { public string Name { get; set; } public string Description { get; set; } }
测试执行时预期抛出的MyExceptions结构如下:
// 抛出的异常结构 { ValidationErrors: [ {Name: "field1", Description: "missing field 1"}, {Name: "field2", Description: "missing field 2"}, ] }
需求为断言异常的ValidationErrors列表中,存在Description值为"missing field 2"的元素。原有断言执行失败,原代码如下:
Assert.That( () => { // 执行业务逻辑,抛出上述结构的MyExceptions }, Throws.TypeOf<MyExceptions>().And .With.Property("ValidationErrors") .Has.One.With.Property("Description").EqualTo("missing field 2") );
失败原因
原写法错误使用了Has.One约束:该约束的语义是被校验的集合总元素数量恰好为1,而示例中ValidationErrors实际包含2个元素,因此断言会直接失败,不会执行后续的属性匹配逻辑。
正确写法
将Has.One替换为Has.Some即可,该约束语义为集合中至少存在一个元素满足后续匹配规则,修正后的链式断言代码:
Assert.That( () => { // 执行业务逻辑抛出异常 }, Throws.TypeOf<MyExceptions>().And .Property("ValidationErrors") .Some.Property("Description").EqualTo("missing field 2") );
优化写法(推荐)
使用nameof运算符替代硬编码的属性名字符串,避免拼写错误导致的测试问题:
Assert.That( () => { // 执行业务逻辑抛出异常 }, Throws.TypeOf<MyExceptions>() .And.Property(nameof(MyExceptions.ValidationErrors)) .Some.Property(nameof(MyValidationError.Description)).EqualTo("missing field 2") );
如果觉得链式约束可读性较差,可以先捕获异常,再单独校验错误集合,逻辑更直观:
// 第一步:断言方法抛出指定类型异常,并捕获异常实例 var exception = Assert.Throws<MyExceptions>(() => { // 执行业务逻辑抛出异常 }); // 第二步:校验异常的错误集合包含目标项 Assert.That( exception.ValidationErrors, Has.Some.Matches<MyValidationError>(err => err.Description == "missing field 2") );
内容的提问来源于stack exchange,提问作者Eric Cheng
相关产品推荐
相关产品推荐

