C# 测试 - 比较自定义类型列表

Posted

技术标签:

【中文标题】C# 测试 - 比较自定义类型列表【英文标题】:C# Testing - compare list of custom type 【发布时间】:2020-06-03 12:53:38 【问题描述】:

我正在尝试编写测试检查 JSON 转换器是否正确反序列化输入到我的自定义列表

    [TestMethod]
    public void JSONInput_Changed()
    
        List<PointOnChart> _expectedPointsOnChart;
        _expectedPointsOnChart = new List<PointOnChart>();
        _expectedPointsOnChart.Add(new PointOnChart  Timestamp = "2020-02-14T09:00:00.000Z", Value1 = 10, Value2 = 20, Value3 = 30 );
        _expectedPointsOnChart.Add(new PointOnChart  Timestamp = "2020-02-14T09:01:00.000Z", Value1 = 11, Value2 = 21, Value3 = 31 );
        _expectedPointsOnChart.Add(new PointOnChart  Timestamp = "2020-02-14T09:02:00.000Z", Value1 = 12, Value2 = 22, Value3 = 32 );
        _expectedPointsOnChart.Add(new PointOnChart  Timestamp = "2020-02-14T09:03:00.000Z", Value1 = 13, Value2 = 23, Value3 = 33 );

        MultipleBarChart multipleBarChartTest = new MultipleBarChart();
        multipleBarChartTest.MeInitialize(DateTimeIntervalType.Minutes);
        string JSONstring = System.IO.File.ReadAllText(@"C:\Users\slawomirk\source\repos\VIXCharts\iFixMultipleBarChartTests\TestJson.txt");
        multipleBarChartTest.JSONInput = JSONstring;
        List<PointOnChart> resultPointsOnChart = multipleBarChartTest.PointsOnChart;

        //bool areEqual = _expectedPointsOnChart.SequenceEqual(resultPointsOnChart);
        IEnumerable<PointOnChart> resultList;
        resultList = _expectedPointsOnChart.Except(resultPointsOnChart);
        if (resultList.Any())
        
            Assert.Fail();
        
    

列表包含该类的对象

public class PointOnChart

    public string Timestamp  get; set; 
    public double Value1  get; set; 
    public double Value2  get; set; 
    public double Value3  get; set; 

这是我正在阅读以反序列化的文件:

["时间戳":"2020-02-14T09:00:00.000Z","Value1":10,"Value2":20,"Value3":30, "时间戳":"2020-02-14T09:01:00.000Z","Value1":11,"Value2":21,"Value3":31, "时间戳":"2020-02-14T09:02:00.000Z","Value1":12,"Value2":22,"Value3":32, "时间戳":"2020-02-14T09:03:00.000Z","Value1":13,"Value2":23,"Value3":33]

我尝试了多种方法来比较两个列表,但都失败了,例如: - 流利的断言 - 集合断言

当我在调试中检查两个列表时,它们是相同的。 我知道这可能很简单,但我可以在网上找到任何解决方案,在此先感谢。

【问题讨论】:

您是否尝试过使用自定义 IEqualityComparer 的SequenceEquals overload?由于您尚未在 PointOnChart 本身中定义确定相等性的方法,因此测试框架将无法判断两者是否相同。 PointOnChart 长什么样子? 【参考方案1】:

您应该为PointOnChart 类实现Equals 方法,如下所示:

public override bool Equals(object other)

    if (object.ReferenceEquals(other, this)) return true;

    var obj = other as PointOnChart;

    if (obj == null) return false;

    return this.Timestamp == obj.Timestamp && this.Value1 == obj.Value1 && this.Value2 == obj.Value2 && this.Value3 == obj.Value3;

这样SequenceEquals 扩展方法将正常运行。

【讨论】:

你忘了GetHashCode() SequenceEquals 将只使用 Equals 方法,但为了完整起见,是的,我们还应该实现 GetHashCode。 你真的应该在它自己的IEqualityComparer&lt;PointOnChart&gt; 类中实现这些方法。否则你可能会遇到尴尬的问题,特别是如果你开始从这个类派生并且其他人开始调用你的Equals()GetHashCode() 方法(如Dictionary&lt;,&gt; 或LINQ 方法如Distinct()Join() 等。 )。 不同意,我认为班级应该知道如何比较自己,这在很多情况下都很有用。【参考方案2】:

与其使用Equals 覆盖来污染您的生产代码,不如考虑使用 www.fluentassertions.com 并将该语句编写为:

resultPointsOnChart.Should().BeEquivalentTo(expectedPointsOnChart);

【讨论】:

完全不同意。我认为班级应该知道如何比较自己,它在很多地方都很有用。 很大程度上取决于该类是否应该具有值语义。如果不是(因为它是域中的实体),那么添加 Equals 会搞砸事情。例如,当您持久化的对象覆盖 Equals 时,NHibernate 会突然表现不同。这与您在单元测试中想要的内容正交。 “搞砸了”?你知道你在说什么吗?这实际上是 NHibernate 必需的 见nhibernate.info/doc/nhibernate-reference/… 嗯,我 25 年了,关于这方面的书很少……但正如我所说,没关系。【参考方案3】:

除了其他答案,我建议像这样实现IEquatable&lt;T&gt; 以及覆盖GetHashCode()Equals(Object)

public class PointOnChart : IEquatable<PointOnChart> 

    public string Timestamp  get; set; 
    public double Value1  get; set; 
    public double Value2  get; set; 
    public double Value3  get; set; 

    public override Int32 GetHashCode() => Timestamp.GetHashCode() ^ Value1.GetHashCode() ^ Value2.GetHashCode() ^ Value3.GetHashCode();

    public override Boolean Equals(Object obj) => Equals(obj as PointOnChart);

    public Boolean Equals(PointOnChart other) => other != null && other.Timestamp == Timestamp && other.Value1.Equals(Value1) && other.Value2.Equals(Value2) && other.Value3.Equals(Value3);


这将为您提供所需的所有比较。 如果您以后需要,还可以更轻松地实现 IEqualityComparerIEqualityComparer&lt;T&gt;

【讨论】:

以上是关于C# 测试 - 比较自定义类型列表的主要内容,如果未能解决你的问题,请参考以下文章

C#调用Webserver自定义类型方法的接口

C#开发的OpenRA使用自定义字典的比较函数

C#开发的OpenRA使用自定义字典的比较函数

WinForms C#中自定义对象类型的跨进程拖放

SharePoint:如何以编程方式将项目添加到自定义列表实例

C#中string类型转换为自定义数据类型怎么转?