You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:54:20