我将在一个提供数据并使用大量数组的API上担任测试人员,因此我决定使用NUnit,LINQ和C#进行一些练习。
为了帮助我'可视化'GruopJoin的actual
结果,作为具有嵌套数组的数组,我正在制作一个等效的expected
对象,然后使用Assert
s进行比较
理想情况下我会使用
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 ) );
按预期工作:)
答案 0 :(得分:2)
如果您的ExamMark
有一个合适的Equals
覆盖(并且它看起来应该是那种类),而您的Performance
做了(并再次看起来像那种使用它的真实代码会发现有用的类,然后你可以使用。
CollectionAssert.AreEqual(expected, actual);
否则,您可以定义IEqualityComparer<Performance>
并使用
CollectionAssert.AreEqual(expected, actual, new PerformanceComparer());
如果您不关心按特定顺序测试的集合,也可以使用CollectionAssert.AreEquivalent
。
当然,Equals
方法必须自己遍历数组,但无论如何都必须采取行动(当然,在不同的长度上快速返回false)。
答案 1 :(得分:0)
首先,要比较集合,最好使用CollectionAssert.AreEqual(IEnumerable expected, IEnumerable actual)
。
此方法存在重载,需要IComparer实现以对两个集合中的各个项进行等效检查。这是一个选项,编写一个实现IComparer
的类并比较两个Performance
个对象。
另一种选择是让所有类都实现IEquatable。然后,您可以使用CollectionAssert.AreEqual
而不使用IComparer
参数。