C# – 在unit testing中断言两个对象是相同的

使用Nunit或Microsoft.VisualStudio.TestTools.UnitTesting。 现在我的断言失败了。

[TestMethod] public void GivenEmptyBoardExpectEmptyBoard() { var test = new Board(); var input = new Board() { Rows = new List() { new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, } }; var expected = new Board() { Rows = new List() { new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, } }; var lifeOrchestration = new LifeOrchestration(); var actual = lifeOrchestration.Evolve(input); Assert.AreEqual(expected, actual); } 

您有两个不同的Board实例,因此您对Assert.AreEqual的调用将失败。 即使它们的全部内容看起来相同,您也要比较参考,而不是基础值。

您必须指定使两个Board实例相等的原因。

您可以在测试中执行此操作:

 Assert.AreEqual(expected.Rows.Count, actual.Rows.Count); Assert.AreEqual(expected.Rows[0].Cells[0], actual.Rows[0].Cells[0]); // Lots more tests of equality... 

或者你可以在你的课堂上做到这一点:( 注意我是在飞行中写的 – 你要调整它)

 public class Board { public List Rows = new List(); public override bool Equals(object obj) { var board = obj as Board; if (board == null) return false; if (board.Rows.Count != Rows.Count) return false; return !board.Rows.Where((t, i) => !t.Equals(Rows[i])).Any(); } public override int GetHashCode() { // determine what's appropriate to return here - a unique board id may be appropriate if available } } public class Row { public List Cells = new List(); public override bool Equals(object obj) { var row = obj as Row; if (row == null) return false; if (row.Cells.Count != Cells.Count) return false; if (row.Cells.Except(Cells).Any()) return false; return true; } public override int GetHashCode() { // determine what's appropriate to return here - a unique row id may be appropriate if available } } 

我曾经覆盖了getHasCode和equals,但我从不喜欢它,因为我不想为了unit testing而改变我的生产代码。 这也是一种痛苦。

然后我转过身来反思来比较那些侵入性较小的物体……但那是很多工作(很多角落的情况)

最后我使用:

http://www.nuget.org/packages/DeepEqual/

效果很好。

ExpectedObjects可以帮助您按属性值比较相等性。 它支持:

  1. simple object:expected.ToExpectedObject()。ShouldEqual(actual);
  2. collection:expected.ToExpectedObject()。ShouldEqual(actual);
  3. composized object:expected.ToExpectedObject()。ShouldEqual(actual);
  4. 部分比较:预期对象需要使用匿名类型设计,并使用expected.ToExpectedObject()。ShouldMatch(actual)

我喜欢ExpectedObjects,因为我只需要调用2个API来断言比较对象的相等性:

  1. ShouldEqual()
  2. ShouldMatch()进行部分比较

我想要一个不需要添加依赖项的解决方案,使用VSunit testing,比较两个对象的字段值,并告诉我所有不相等的字段。 这就是我提出的。 请注意,它也可以扩展为使用属性值。

在我的例子中,这适用于比较某些文件解析逻辑的结果,以确保两个技术上“不同”的条目具有相同值的字段。

  public class AssertHelper { public static void HasEqualFieldValues(T expected, T actual) { var failures = new List(); var fields = typeof(T).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); foreach(var field in fields) { var v1 = field.GetValue(expected); var v2 = field.GetValue(actual); if (v1 == null && v2 == null) continue; if(!v1.Equals(v2)) failures.Add(string.Format("{0}: Expected:<{1}> Actual:<{2}>", field.Name, v1, v2)); } if (failures.Any()) Assert.Fail("AssertHelper.HasEqualFieldValues failed. " + Environment.NewLine+ string.Join(Environment.NewLine, failures)); } } [TestClass] public class AssertHelperTests { [TestMethod] [ExpectedException(typeof(AssertFailedException))] public void ShouldFailForDifferentClasses() { var actual = new NewPaymentEntry() { acct = "1" }; var expected = new NewPaymentEntry() { acct = "2" }; AssertHelper.HasEqualFieldValues(expected, actual); } } 

断言方法依赖于对象的Equals和GetHashcode。 你可以实现它,但如果在unit testing之外不需要这个对象相等,我会考虑比较对象上的各个基本类型。 看起来这些对象很简单,并且不能保证等于等于对等。