流利断言:字典应该等效于排除字典值上的属性

Tol*_*vic 2 c# linq nunit fluent-assertions

我有一个名为 HandRank 的类,它有一个 Id 属性。Id 属性是由我的数据库生成的。

public class HandRank
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int Rank { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我有一个名为 GetHandRanks 的方法,它返回一个Dictionary<string, HandRank>.

在我的测试中,我正在内存数据库中播种。由于 Id 属性是由数据库确定的,因此我希望将其从我的断言中排除。

下面是我的测试,但它失败了,因为 Id 属性未在预期结果中设置。我没有设置 Id,因为我不知道数据库生成时的 Id 是什么。

[Test]
public void Test()
{
    // arrange
    var expectedResult = new Dictionary<string, HandRank>
    {
        { "aaa", new HandRank { Rank = 1} },
        { "bbb", new HandRank { Rank = 2} }
    };

    // act
    var actualResult = _handRankManager.GetHandRanks();

    // Assert
    actualResult.Should().BeEquivalentTo(expectedResult);
}
Run Code Online (Sandbox Code Playgroud)

我预计断言需要类似于下面的内容,但我无法正确获取排除方法中的 lambda。

actualResult.Should().BeEquivalentTo(expectedResult, options => options.Excluding(x => x.Values.Id));
Run Code Online (Sandbox Code Playgroud)

NPr*_*ras 6

首先,如果您只想过滤掉HandRank.Id,那么您可以使用以下内容:

actualResult.Should().BeEquivalentTo(expectedResult, opt =>
    opt.Excluding(m => 
        m.SelectedMemberInfo.DeclaringType == typeof(HandRank) 
        && m.SelectedMemberInfo.Name.Equals(nameof(HandRank.Id))
    ));
Run Code Online (Sandbox Code Playgroud)

如果"Id"您想在测试的许多部分中使用忽略指定属性,那么最好将其放入如下函数中:

public static EquivalencyAssertionOptions<_> ExcludeId<_>(EquivalencyAssertionOptions<_> opt)
    => opt.Excluding(m => m.SelectedMemberInfo.Name.Equals("Id"));
Run Code Online (Sandbox Code Playgroud)

并按如下方式使用它:

actual.Should().BeEquivalentTo(expected, ExcludeId);
Run Code Online (Sandbox Code Playgroud)

应该适用于字典,列表,具有深层属性的对象,任何你能想到的东西。它将忽略所有名为 的成员Id


2022 年编辑:

根据下面的反馈,6.0 进行了一项重大更改SelectedMemberInfo,将属性扁平化为IMemberInfo,这使得排除更易于阅读。

actual.Should().BeEquivalentTo(expected, opt =>
  opt.Excluding(member => 
    member.DeclaringType == typeof(X) 
    && member.Name.Equals(nameof(X.Id))
  ));
Run Code Online (Sandbox Code Playgroud)