0

我将在一个提供数据并使用大量数组的 API 上担任测试员,因此我决定使用 NUnit、LINQ 和 C# 进行一些练习。

为了帮助我“可视化” actualGruopJoin 的结果,作为具有嵌套数组的数组,我正在制作一个等效expected对象,然后使用Asserts.

理想情况下我会使用

 Assert.That( actual, Is.EqualTo( expected ) );

但这失败并显示以下消息:

NUnitExamples.TestFixture1.LinqOuterJoinMultirelation_Anon:预期和实际都是索引 [0] 处的值不同预期:但是是:

我想这告诉我对象引用是不同的。我想知道的是,它们是等价的对象,即属性值都相等吗?

遍历数组元素属性,包括嵌套数组及其属性,告诉我对象是等效的,但如果非常冗长。有没有更简单的方法来做同样的事情?

这是我的代码(顺便说一句,欢迎对我的代码提出任何批评,因为我正在从新学习这一切):

[Test]
public void LinqOuterJoinMultirelation_Anon()
{
    Course[] curriculum = 
    { 
        new Course() { CourseId = "C1", Title = "Database" },
        new Course() { CourseId = "C2", Title = "HCI" },
        new Course() { CourseId = "C3", Title = "Op Systems" },
        new Course() { CourseId = "C4", Title = "Programming" }
    };

    ExamMark[] results = 
    { 
        new ExamMark() { StudentId = "S1", CourseId = "C1", Mark = 85 },
        new ExamMark() { StudentId = "S1", CourseId = "C2", Mark = 49 },
        new ExamMark() { StudentId = "S1", CourseId = "C3", Mark = 85 },
        new ExamMark() { StudentId = "S2", CourseId = "C1", Mark = 49 },
        new ExamMark() { StudentId = "S3", CourseId = "C3", Mark = 66 },
        new ExamMark() { StudentId = "S4", CourseId = "C1", Mark = 93 }
    };

    var actual = curriculum.GroupJoin
    (
        results, 
        c => c.CourseId, 
        r => r.CourseId, 
        (c, r) => new Performance() { CourseId = c.CourseId, Results = r.ToArray<ExamMark>() }
    ).ToArray<Performance>();

    var expected = new[] 
    { 
        new Performance 
        { 
            CourseId = "C1", 
            Results = new[] 
            { 
                new ExamMark() { StudentId = "S1", CourseId = "C1", Mark = 85 }, 
                new ExamMark() { StudentId = "S2", CourseId = "C1", Mark = 49 },
                new ExamMark() { StudentId = "S4", CourseId = "C1", Mark = 93 }
            }
        },
        new Performance 
        { 
            CourseId = "C2", 
            Results = new[] 
            { 
                new ExamMark() { StudentId = "S1", CourseId = "C2", Mark = 49 }
            }
        },
        new Performance 
        { 
            CourseId = "C3", 
            Results = new[] 
            { 
                new ExamMark() { StudentId = "S1", CourseId = "C3", Mark = 85 },
                new ExamMark() { StudentId = "S3", CourseId = "C3", Mark = 66 }
            }
        },
        new Performance { CourseId = "C4" }
    };

    //Assert.That( actual, Is.EqualTo( expected ) );

    for (int i = 0; i < actual.Count(); i++)
    {
        Assert.That( actual[i].CourseId, Is.EqualTo( expected[i].CourseId ) );

        for (int j = 0; j < actual[i].Results.Count(); j++)
        {
            Assert.That( actual[i].Results[j].StudentId, Is.EqualTo( expected[i].Results[j].StudentId ) );
            Assert.That( actual[i].Results[j].CourseId, Is.EqualTo( expected[i].Results[j].CourseId ) );
            Assert.That( actual[i].Results[j].Mark, Is.EqualTo( expected[i].Results[j].Mark ) );
        }
    }


class Course
{
    public string CourseId { get; set; }
    public string Title { get; set; }
}

class ExamMark
{
    public string StudentId { get; set; }
    public string CourseId { get; set; }
    public int Mark { get; set; }
}

class Performance
{
    public string CourseId { get; set; }
    public ExamMark[] Results { get; set; }
}

解决

我更改了要实现的类,IEquatable<T>包括覆盖,Equals并发现我的expected对象不等同于actual由于空数组引用而不是零元素数组,即需要从

new Performance { CourseId = "C4" }

new Performance { CourseId = "C4" , Results = new ExamMark[0] }

现在Assert.That( actual, Is.EqualTo( expected ) );按预期工作:)

4

2 回答 2

2

如果你ExamMark有一个合适的Equals覆盖(它看起来应该是那种类),并且你Performance做了(同样,它看起来像是使用它的真实代码会发现有用的那种类),那么你可以使用。

CollectionAssert.AreEqual(expected, actual);

否则,您可以定义一个IEqualityComparer<Performance>并使用

CollectionAssert.AreEqual(expected, actual, new PerformanceComparer());

CollectionAssert.AreEquivalent如果您不关心测试的集合是否按特定顺序排列,您也可以使用。

当然,这些Equals方法必须自己遍历数组,但无论如何都必须这样做(当然,在不同的长度上快速返回 false)。

于 2012-08-31T09:27:09.027 回答
0

首先,要比较您最好使用的集合CollectionAssert.AreEqual(IEnumerable expected, IEnumerable actual)

此方法有一个重载,它采用IComparer实现来对两个集合中的各个项目进行等效检查。这将是一种选择,编写一个实现IComparer和比较两个Performance对象的类。

另一种选择是让您的所有类都实现IEquatable。然后你可以CollectionAssert.AreEqual不带IComparer参数使用。

于 2012-08-31T09:28:16.327 回答