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

如何用Lambda函数创建NUnit约束以验证类实例属性一致性

实现NUnit自定义约束以清晰展示A类实例属性对比结果

1. 自定义NUnit约束类

继承NUnit的Constraint基类,实现自定义验证逻辑和失败消息输出,完全规避ToString的歧义问题:

using NUnit.Framework.Constraints;

public class SameAAndBConstraint : Constraint
{
    private readonly A _expectedInstance;

    public SameAAndBConstraint(A expected)
    {
        _expectedInstance = expected;
    }

    // 核心验证逻辑:精准对比PropertyA和PropertyB
    public override ConstraintResult ApplyTo<TActual>(TActual actual)
    {
        if (actual is not A actualInstance)
        {
            return new ConstraintResult(this, actual, ConstraintStatus.Failure);
        }

        bool matches = actualInstance.PropertyA.Equals(_expectedInstance.PropertyA) &&
                       actualInstance.PropertyB.Equals(_expectedInstance.PropertyB);

        return new ConstraintResult(this, actual, matches ? ConstraintStatus.Success : ConstraintStatus.Failure);
    }

    // 输出期望实例的属性详情
    public override void WriteDescriptionTo(MessageWriter writer)
    {
        writer.Write($"instance of {typeof(A).Name} with PropertyA='{_expectedInstance.PropertyA}', PropertyB='{_expectedInstance.PropertyB}'");
    }

    // 输出实际实例的属性详情
    public override void WriteActualValueTo(MessageWriter writer)
    {
        if (ActualValue is A actualInstance)
        {
            writer.Write($"instance of {typeof(A).Name} with PropertyA='{actualInstance.PropertyA}', PropertyB='{actualInstance.PropertyB}'");
        }
        else
        {
            base.WriteActualValueTo(writer);
        }
    }
}

2. 封装便捷调用方法

通过静态扩展方法让测试代码更简洁:

using NUnit.Framework.Constraints;

public static class AConstraintExtensions
{
    public static SameAAndBConstraint SameAAndBAs(this ConstraintExpression expression, A expected)
    {
        var constraint = new SameAAndBConstraint(expected);
        expression.Append(constraint);
        return constraint;
    }
}

3. 编写测试用例

使用简洁语法编写测试,失败时会输出明确的属性对比信息:

[TestFixture]
public class ATests
{
    [Test]
    public void When_InstancesHaveDifferentPropertyB_ShouldFail()
    {
        var a1 = new A("wordA", "wordB");
        var a2 = new A("wordA", "wordC");

        Assert.That(a1, Has.SameAAndBAs(a2));
    }

    [Test]
    public void When_PropertiesContainCommas_ShouldDistinguish()
    {
        var a1 = new A("wordA, wordB", "wordC");
        var a2 = new A("wordA", "wordB, wordC");

        Assert.That(a1, Has.SameAAndBAs(a2));
    }
}

失败消息示例

当第二个测试失败时,NUnit会输出:

Expected: instance of A with PropertyA='wordA', PropertyB='wordB, wordC'
But was: instance of A with PropertyA='wordA, wordB', PropertyB='wordC'

清晰展示两个实例的关键属性值,完全避免了ToString的歧义问题。

补充说明

  • 原类A的ToString方法存在笔误,应使用PropertyA和PropertyB而非Property1/Property2,建议修正。
  • 自定义约束的优势在于完全控制验证逻辑和错误提示,不受类自身ToString实现的限制,适合需要精准对比的场景。

内容的提问来源于stack exchange,提问作者suitendaal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:27:21