1

我正在使用 DeepEqual 库来测试测试结果是否符合我的预期输出。

我简单地做比较

results.ShouldDeepEqual(expected);

但是,我不知道如何忽略列表类型中的属性

我正在深入比较的类型包含一个列表。此列表中保存的数据类型包含一个我想忽略的Guid属性Id以及一个日期。

忽略顶级属性可以正常工作。但是,我看不到如何忽略列表类型的属性。

为了暂时解决这个问题,我不得不自己编写一些代码来清除这些属性,但这显然并不理想。

for (var i = 0; i < results.MyList.Count; i++)
{
    results.MyList[i].Id = Guid.Empty;
    expectedResults.MyList[i].Id = Guid.Empty;
}

我怎样才能做到这一点?

4

2 回答 2

0

查看DeepEqual的源代码,该库允许通过IComparison界面进行自定义比较。有了这个,我模拟了您需要的模型:

public class MyClass
{
    public MyClass()
    {
        MyList = new List<MySubClass>(new[]
        {
            new MySubClass {Id = Guid.Parse("1".PadLeft(32, '0')), Name = "Foo"}, 
            new MySubClass {Id = Guid.Parse("2".PadLeft(32, '0')), Name = "Bar"}, 
            new MySubClass {Id = Guid.Parse("3".PadLeft(32, '0')), Name = "Test"}, 
        });
    }

    public MyClass(params MySubClass[] subs)
    {
        MyList = new List<MySubClass>(subs);
    }
    
    public List<MySubClass> MyList { get; set; }
}

public class MySubClass
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

然后我继续创建一个自定义IComparison类:

public class MySubClassComparer : IComparison
{
    public bool CanCompare(Type type1, Type type2)
    {
        return type1 == type2 && type1 == typeof(MySubClass);
    }

    public (ComparisonResult result, IComparisonContext context) Compare(IComparisonContext context, object value1, object value2)
    {
        if (value1 is MySubClass first && value2 is MySubClass second)
        {
            if (first.Name == second.Name)
            {
                return (ComparisonResult.Pass, context);
            }
        }

        return (ComparisonResult.Fail, context);
    }
}

这是我通过的两个单元测试:

[Fact]
public void IsDeepEqual_ShouldReturnTrue_WhenListHasSameNames()
{
    // Arrange
    MyClass sut = new MyClass();
    MyClass parameter = new MyClass(new[]
    {
        new MySubClass {Id = Guid.Parse("4".PadLeft(32, '0')), Name = "Foo"},
        new MySubClass {Id = Guid.Parse("5".PadLeft(32, '0')), Name = "Bar"},
        new MySubClass {Id = Guid.Parse("6".PadLeft(32, '0')), Name = "Test"},
    });
    var comparer = new ComparisonBuilder().WithCustomComparison(new MySubClassComparer()).Create();

    // Act
    bool result = sut.IsDeepEqual(parameter, comparer);

    // Assert
    Assert.True(result);
}

[Fact]
public void IsDeepEqual_ShouldReturnFalse_WhenListHasDifferentNames()
{
    // Arrange
    MyClass sut = new MyClass();
    MyClass parameter = new MyClass(new[]
    {
        new MySubClass {Id = Guid.Parse("4".PadLeft(32, '0')), Name = "Foo"},
        new MySubClass {Id = Guid.Parse("5".PadLeft(32, '0')), Name = "Bar"},
        new MySubClass {Id = Guid.Parse("6".PadLeft(32, '0')), Name = "Fail"},
    });
    var comparer = new ComparisonBuilder().WithCustomComparison(new MySubClassComparer()).Create();

    // Act
    bool result = sut.IsDeepEqual(parameter, comparer);

    // Assert
    Assert.False(result);
}

备注 此比较应忽略该Id属性,但不确定这是否是完成任务的最佳方式。有一个IgnoreProperty方法可能更适合该任务,但目前看不到让它工作的方法。

如果有人比我对图书馆有更多的经验,请让我知道更好的方法,我会相应地更新我的答案。

于 2020-11-08T22:27:45.747 回答
0

DeepEqual库现在使它变得非常简单。写下就足够了:

results.WithDeepEqual(expected).IgnoreProperty<MySubClass>(x => x.Id).Assert();

如果我们采用Hayden单元测试并稍微补充它们,你会得到这样的结果:

using System;
using Xunit;
using DeepEqual.Syntax;
using System.Collections.Generic;

public class MyClass
{
    public List<MySubClass> MyList { get; } = new List<MySubClass>
    {
        new MySubClass {Id = Guid.NewGuid(), Name = "Foo"},
        new MySubClass {Id = Guid.NewGuid(), Name = "Bar"},
        new MySubClass {Id = Guid.NewGuid(), Name = "Test"}
    };
}

public class MySubClass
{
    public Guid Id { get; init; }

    public string Name { get; init; }
}

public class DeepEqualTests
{
    [Fact]
    public void FullDeepEqualTest()
    {
        // Arrange
        var first = new MyClass();
        var second = new MyClass();

        // Act
        Action compassion = () => first
            .ShouldDeepEqual(second);

        // Assert
        Assert.Throws<DeepEqualException>(compassion);
    }

    [Fact]
    public void DeepEqualWithoutIdTest()
    {
        // Arrange
        var first = new MyClass();
        var second = new MyClass();

        // Act
        Action compassion = () => first
            .WithDeepEqual(second)
            .IgnoreProperty<MySubClass>(x => x.Id)
            .Assert();

        // Assert
        compassion();
    }
}

第一个测试是一个完整的比较,并期待一个例外。第二个测试在比较时会忽略 ID 字段,如果没有抛出异常则成功。两个测试都成功运行

于 2021-10-21T13:26:57.197 回答