如何使用Fluent Assertions进行多个断言?

本文讨论了在.NET中进行单元测试时,如何处理复杂对象的维护问题,提出使用值元组和FluentAssertions的Json功能来减少断言行数,提高测试效率和可维护性。
摘要由CSDN通过智能技术生成

目录

介绍

背景

使用代码

兴趣点


介绍

许多代码返回一个复杂的对象。就像其他代码一样,它需要进行单元测试。从逻辑上讲,这只需在测试中添加多个断言行即可完成。这听起来合乎逻辑,但对维护来说是一个问题。每增加一行都需要维护。此外,每条线路都可能导致单独的故障。

在本文中,我将更详细地解释该问题,并演示如何处理此问题。

背景

必须具备一些.NET中的单元测试经验,最好是xUnit Fluent断言

使用代码

下面是要进行单元测试的代码。它是一个拥有关于人类健康的属性的类。由于无法测量BMI,因此对其进行计算。

public class HealthDescription
{
    public decimal LengthInM { get; }
    public decimal WeightInKg { get; }
    public decimal Bmi { get;  }
    public HealthDescription(decimal weightInKg, int lengthInCm)
    {
        WeightInKg = weightInKg;
        LengthInM = (decimal)lengthInCm / 100;
        Bmi = Math.Round(weightInKg / (LengthInM * LengthInM), 2);
    }
}

要演示的第一个单元测试是这样的:

[Theory]
[InlineData(70.01, 180, 1.80, 21.61)]
public void RegularTest(decimal weightInKg, int lengthInCm, 
       decimal expectedLengthInM, decimal expectedBmi)
{
    var instance = new HealthDescription(weightInKg, lengthInCm);
    instance.LengthInM.Should().Be(expectedLengthInM);
    instance.Bmi.Should().Be(expectedBmi);
    instance.WeightInKg.Should().Be(weightInKg);
}

上面显示的这个测试有两个问题:

  1. 有多条线路需要维护。
  2. 如果第一个或第二个断言失败,则并非所有断言都会执行。

最后一个问题很容易解决。这里有一种方法可以做到这一点:

[Theory]
[InlineData(70.01, 180, 1.80, 21.61)]
public void ScopeTest(decimal weightInKg, int lengthInCm, 
       decimal expectedLengthInM, decimal expectedBmi)
{
    var instance = new HealthDescription(weightInKg, lengthInCm);
    using (new AssertionScope())
    {
        instance.LengthInM.Should().Be(expectedLengthInM);
        instance.Bmi.Should().Be(expectedBmi);
        instance.WeightInKg.Should().Be(weightInKg);
    }
}

我们只需将多行包装到一个断言作用域中,以确保执行所有验证(因为这些是同一作用域的一部分)。但是,提到的第一个问题是行数。这只会使情况变得更糟。

因此,我们需要进一步寻找解决这两个问题的真正解决方案。这里有一个解决方案:使用值元组。

[Theory]
[InlineData(70.01, 180, 1.80, 21.61)]
public void ValueTupleTest(decimal weightInKg, int lengthInCm, 
                           decimal expectedLengthInM, decimal expectedBmi)
{
    var instance = new HealthDescription(weightInKg, lengthInCm);
    (instance.LengthInM, instance.Bmi, instance.WeightInKg).Should()
        .Be((expectedLengthInM, expectedBmi, weightInKg));
}

此代码背后的思想是将要验证的属性包装到一个对象中。然后,只需要一个验证(行)。此外,还有一个额外的解决方案,即将 FluentAssertions.Json 文本字符串组合在一起。这样,具有要验证的属性的json对象就会被验证为一个对象。

[Theory]
[InlineData(70.01, 180, """
                        {
                        "Bmi" : 21.61,
                        "WeightInKg": 70.01,
                        "LengthInM" : 1.80 
                        }
                        """)]
public void RegularJsonTest(decimal weightInKg, int lengthInCm, string expectedResult)
{
    var instance = new HealthDescription(weightInKg, lengthInCm);
    JToken.FromObject(instance).Should().BeEquivalentTo(JToken.Parse(expectedResult));
}

兴趣点

在研究如何进行多个断言的可能性时,我发现很多人一直在使用他们多年来一直使用的方式。由于这些方法仍然有效,他们继续使用它。但是,最近添加的C#功能为以更有效的方式解决同一问题创造了新的可能性。本文中使用的源代码可以在这里找到。

https://www.codeproject.com/Tips/5366616/How-to-do-Multiple-Assertions-with-Fluent-Assertio

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值