public void CompareIEnumerable() { Element leftObject = new Element() { Name = "root", Content = new List <string> { "hello1", "hello2", "hello3" } }; Element rightObject = new Element() { Name = "root", Content = new List <string> { "hello1", "hello2", "hello3" } }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "objects did not match"); }
public void CompareTypesDoNotMatch() { var leftObject = new Element() { Content = 32, }; var rightObject = new Element() { Content = "stringvalue", }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); IEnumerable <ObjectComparisonMismatch> mismatches; bool match = comparer.Compare(left, right, out mismatches); string[] expectedMismatches = new string[] { "ObjectTypesDoNotMatch:Left=RootObject.Content(32) Right=RootObject.Content(stringvalue)", }; string[] actualMismatches = TestHelpers.StringFromMismatches(mismatches); Assert.False(match); Assert.True(actualMismatches.Length == expectedMismatches.Length); for (int index = 0; index < expectedMismatches.Length; index++) { Assert.Equal(expectedMismatches[index], actualMismatches[index]); } }
public void ObjectGraphComparisonStrategyCommentSample() { var l1 = new Sample("SAmplE", null); var l2 = new Sample("1", l1); var l3 = new Sample("TeeST", l2); var l4 = new Sample("2", l3); l1.Child = l4; // l4 -> l3 -> l2 -> l1 -> l4 var r1 = new Sample("sample", null); var r2 = new Sample("1", r1); var r3 = new Sample("TeeeST", r2); var r4 = new Sample("2", r3); r1.Child = r4; var factory = new SampleFactory(); var graph1 = factory.CreateObjectGraph(l4); var graph2 = factory.CreateObjectGraph(r4); IEnumerable <ObjectComparisonMismatch> mismatches; var result = new ObjectGraphComparer().Compare(graph1, graph2, out mismatches); Assert.False(result); Assert.Equal(1, mismatches.Count()); var expected = "ObjectValuesDoNotMatch:Left=Sample.Sample(TeeST) Right=Sample.Sample(TeeeST)"; var actual = TestHelpers.StringFromMismatches(mismatches)[0]; Assert.Equal(expected, actual); }
public void BasicTypesDiffer() { BasicTypes leftObject = new BasicTypes() { BoolPrimitive = false, BytePrimitive = byte.MinValue, CharValue = char.MinValue, DoublePrimitive = double.MinValue, FloatPrimitive = float.MinValue, IntPrimitive = int.MinValue, LongPrimitive = long.MinValue, ShortPrimitive = short.MinValue, StringPrimitive = "some string", TimeSpanValue = TimeSpan.MinValue, }; BasicTypes rightObject = leftObject.Clone(); ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "Basic types did not match"); }
public void HandlesPropertiesWithNullValues() { // There was a bug that PublicPropertyObjectGraphFactory threw // NullReferenceException when // 1. factoryMap is not null // 2. Property value is null // This test case is to make sure that this bug has been fixed and // does not come back var left = typeof(string); var right = typeof(string); var fac = new PublicPropertyObjectGraphFactory(); var comparer = new ObjectGraphComparer(); var factoryMap = new ObjectGraphFactoryMap(false); factoryMap.Add(typeof(MethodBase), new StubGraphFactory()); factoryMap.Add(typeof(Assembly), new StubGraphFactory()); var leftNode = fac.CreateObjectGraph(left, factoryMap); // With StubFactory var rightNode = fac.CreateObjectGraph(right); // Without StubFactory bool noDifferences = comparer.Compare(leftNode, rightNode); Assert.False(noDifferences); var leftChildrenCount = leftNode.GetNodesInDepthFirstOrder().Count(); var rightChildrenCount = rightNode.GetNodesInDepthFirstOrder().Count(); // Make sure that we reduced size of the object graph by using StubFactory Assert.True(leftChildrenCount < rightChildrenCount); }
public static void CompareObjects(ObjectComparisonCmdletBase cmdlet, object referenceObject, object[] differenceObjects) { // left is null if (null == referenceObject) { cmdlet.WriteObject(cmdlet, false); return; } // right is null if (null == differenceObjects) { cmdlet.WriteObject(cmdlet, false); return; } if (null != differenceObjects && 0 < differenceObjects.Length) { ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphFactoryMap map = new ObjectGraphFactoryMap(true); GraphNode referenceGraph = factory.CreateObjectGraph(referenceObject, map); foreach (var differenceObject in differenceObjects) { cmdlet.WriteVerbose(cmdlet, "comparing " + referenceObject + " and " + differenceObject); GraphNode differenceGraph = factory.CreateObjectGraph(differenceObject, map); ObjectGraphComparer comparer = new ObjectGraphComparer(); bool result = comparer.Compare(referenceGraph, differenceGraph); cmdlet.WriteObject(cmdlet, result); } } }
public void ObjectGraphCodecExampleCodecCommentSample() { // Example code begins here // var p1 = new Person("John"); p1.Children.Add(new Person("Peter")); p1.Children.Add(new Person("Mary")); // Create a sample object graph var factory = new PublicPropertyObjectGraphFactory(); var graph1 = factory.CreateObjectGraph(p1); // Encode that object graph var stream = new MemoryStream(); var codec = new SimpleCodec(); codec.EncodeObjectGraph(graph1, stream); // Print the result Console.WriteLine(Encoding.UTF8.GetString(stream.GetBuffer())); // Decode the object graph var graph2 = codec.DecodeObjectGraph(stream); // Result should be false, because we encoded only tree top nodes // from the whole object graph var result = new ObjectGraphComparer().Compare(graph1, graph2); Trace.WriteLine("{0}", result ? "Object graphs are equal!" : "Object graphs are NOT equal!"); // Example code ends here // Assert.False(result); }
public void CompareObjectWithLoopInSecondLevel() { Element leftObject = new Element() { Name = "RootElement", Content = new Element() { Name = "ChildElement" } }; // child points to root ((Element)leftObject.Content).Content = leftObject; Element rightObject = new Element() { Name = "RootElement", Content = new Element() { Name = "ChildElement" } }; // child points to parent ((Element)rightObject.Content).Content = rightObject; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "object with loop did not match"); }
public void CompareEqualCyclicGraphsDifferentOrder() { var root1 = new GraphNode { Name = "RootNode" }; { var child1 = new GraphNode { Name = "Name", Parent = root1, ObjectValue = "Peter" }; var child2 = new GraphNode { Name = "Value", Parent = root1 }; var child3 = new GraphNode { Name = "Value", Parent = root1 }; var child21 = new GraphNode { Name = "Grandchild", Parent = child2, ObjectValue = 1 }; root1.Children.Add(child1); root1.Children.Add(child2); root1.Children.Add(child3); child2.Children.Add(child21); child21.Children.Add(root1); } var root2 = new GraphNode { Name = "RootNode" }; { var child1 = new GraphNode { Name = "Name", Parent = root2, ObjectValue = "Peter" }; var child3 = new GraphNode { Name = "Value", Parent = root2 }; var child2 = new GraphNode { Name = "Value", Parent = root2 }; var child21 = new GraphNode { Name = "Grandchild", Parent = child2, ObjectValue = 1 }; root2.Children.Add(child1); root2.Children.Add(child3); root2.Children.Add(child2); child2.Children.Add(child21); child21.Children.Add(root2); } var result = new ObjectGraphComparer().Compare(root1, root2); Assert.True(result); }
// <summary> // Compare two object trees. If all the descendant logical nodes // are equivalent, return true, otherwise, return false. // </summary> // <param name="firstTree">The root for the first tree</param> // <param name="secondTree">The root for the second tree</param> // <remarks> // Compares every event and property for each the node. // </remarks> // <returns> // A structure containing result. If the returned variable name is result. // result.Result is CompareResult.Equivalent in the case two nodes are equivalent, // and CompareResult.Different otherwise. // </returns> public static TreeComparerResult CompareLogical( Object firstTree, Object secondTree) { TreeComparerResult result = TreeComparer.CompareLogical(firstTree, secondTree, TreeComparer._skipPropertiesDefault); ObjectGraphComparer.XamlCompareParity(firstTree, secondTree, result.Result); return(result); }
public void XmlObjectGraphCodecRoundtripCommentSample() { var expectedXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + @"<RootObject> <Name>John</Name> <Children> <Count>2</Count> <IEnumerable0> <Name>Peter</Name> <Children> <Count>0</Count> </Children> </IEnumerable0> <IEnumerable1> <Name>Mary</Name> <Children> <Count>0</Count> </Children> </IEnumerable1> </Children> </RootObject>"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(expectedXml)); // Example code starts here // var p1 = new Person("John"); p1.Children.Add(new Person("Peter")); p1.Children.Add(new Person("Mary")); // Create an object graph var factory = new PublicPropertyObjectGraphFactory(); var graph1 = factory.CreateObjectGraph(p1); // Simulate round-trip data loss { var roundtripStream = new MemoryStream(); var xmlCodec = new XmlObjectGraphCodec(); xmlCodec.EncodeObjectGraph(graph1, roundtripStream); graph1 = xmlCodec.DecodeObjectGraph(stream); } // Decode a baseline graph from the earlier prepared stream var graph2 = new XmlObjectGraphCodec().DecodeObjectGraph(stream); var result = new ObjectGraphComparer().Compare(graph1, graph2); Trace.WriteLine("{0}", result ? "Object graphs are equal!" : "Object graphs are NOT equal!"); // Example code ends here // Assert.True(result); }
public void CompareObjects() { // Create two objects with differing property values Person leftObject = new Person() { Name = "Person1", Age = 15, Parent = new Person() { Name = "ParentOfPerson1", } }; Person rightObject = new Person() { Name = "Person2", Age = 15, Parent = new Person() { Name = "ParentOfPerson2", } }; // Create the object graph factory ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); var leftGraph = factory.CreateObjectGraph(leftObject); var rightGraph = factory.CreateObjectGraph(rightObject); // Create a comparer using the factory ObjectGraphComparer comparer = new ObjectGraphComparer(); // Compare the objects IEnumerable <ObjectComparisonMismatch> mismatches; bool match = comparer.Compare(leftGraph, rightGraph, out mismatches); // Validate the mismatches when the objects do not match string[] expectedMismatches = new string[] { "ObjectValuesDoNotMatch:Left=RootObject.Name(Person1) Right=RootObject.Name(Person2)", "ObjectValuesDoNotMatch:Left=RootObject.Parent.Name(ParentOfPerson1) Right=RootObject.Parent.Name(ParentOfPerson2)", }; string[] actualMismatches = StringFromMismatches(mismatches); Assert.False(match); Assert.True(actualMismatches.Length == expectedMismatches.Length); for (int index = 0; index < expectedMismatches.Length; index++) { Assert.Equal(expectedMismatches[index], actualMismatches[index]); } }
public void IfSetDoesNotThrowOnUnknownComparisonStrategy() { var root = new GraphNode { Name = "Root", ComparisonStrategy = new IgnoreCaseComparisonStrategy() }; var decoded = TestHelpers.XmlCodecRoundtrip(root, false); IEnumerable <ObjectComparisonMismatch> mismatches; var result = new ObjectGraphComparer().Compare(root, decoded, out mismatches); Assert.False(result); Assert.Equal(1, mismatches.Count()); var expected = "ComparisonStrategiesDoNotMatch:Left=Root(Null) Right=Root(Null)"; var actual = TestHelpers.StringFromMismatches(mismatches)[0]; Assert.Equal(expected, actual); }
public void CompareIncorrectChildCount() { var leftObject = new Element() { Content = new string[] { "String1", "String2", }, }; var rightObject = new Element() { Content = new string[] { "String1", }, }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); IEnumerable <ObjectComparisonMismatch> mismatches; bool match = comparer.Compare(left, right, out mismatches); string[] expectedMismatches = new string[] { "RightNodeHasFewerChildren:Left=RootObject.Content(System.String[]) Right=RootObject.Content(System.String[])", "MissingRightNode:Left=RootObject.Content.IEnumerable1(String2) Right=Null(Null)", "ObjectValuesDoNotMatch:Left=RootObject.Content.Length(2) Right=RootObject.Content.Length(1)", "ObjectValuesDoNotMatch:Left=RootObject.Content.LongLength(2) Right=RootObject.Content.LongLength(1)", }; string[] actualMismatches = TestHelpers.StringFromMismatches(mismatches); Assert.False(match); Assert.True(actualMismatches.Length == expectedMismatches.Length); for (int index = 0; index < expectedMismatches.Length; index++) { Assert.Equal(expectedMismatches[index], actualMismatches[index]); } }
public void CustomFactoryMismatch() { TypeWithAttributedProperty leftObject = new TypeWithAttributedProperty() { PropertyWithoutTestAttribute = "Should not be compared", PropertyWithTestAttribute = "Should be compared", }; TypeWithAttributedProperty rightObject = new TypeWithAttributedProperty() { PropertyWithoutTestAttribute = "Should not be compared - so this is different", PropertyWithTestAttribute = "Should be compared - and should fail because its different", }; ExtractAttributeObjectGraphFactory factory = new ExtractAttributeObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); Assert.False(comparer.Compare(left, right), "Custom compare passed when it should have failed"); }
public static void CompareObjects(ObjectComparisonCmdletBase cmdlet, object referenceObject, object[] differenceObjects) { // left is null // right is null if (null != differenceObjects && 0 < differenceObjects.Length) { ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); GraphNode referenceGraph = factory.CreateObjectGraph(referenceObject, null); foreach (var differenceObject in differenceObjects) { GraphNode differenceGraph = factory.CreateObjectGraph(differenceObject, null); ObjectGraphComparer comparer = new ObjectGraphComparer(); bool result = comparer.Compare(referenceGraph, differenceGraph); cmdlet.WriteObject(cmdlet, result); } } }
public void CompareDictionary() { Dictionary <int, string> leftObject = new Dictionary <int, string>() { { 10, "Hello" }, { 20, "World" }, }; Dictionary <int, string> rightObject = new Dictionary <int, string>() { { 10, "Hello" }, { 20, "World" }, }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "Dictionary<int, string> did not match"); }
public void CompareList() { List <string> leftObject = new List <string>() { "Hello", "World", }; List <string> rightObject = new List <string>() { "Hello", "World", }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "List<string> did not match"); }
public void CompareMissingNodes() { var leftObject = new Element() { Name = "Content1", Content = new Element() { Name = "OnlyOnLeft", } }; var rightObject = new Element() { Name = "Content1" }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); IEnumerable <ObjectComparisonMismatch> mismatches; bool match = comparer.Compare(left, right, out mismatches); string[] expectedMismatches = new string[] { "ObjectValuesDoNotMatch:Left=RootObject.Content(Microsoft.Test.AcceptanceTests.ObjectComparison.Element) Right=RootObject.Content(Null)", "MissingRightNode:Left=RootObject.Content.Content(Null) Right=Null(Null)", "MissingRightNode:Left=RootObject.Content.Name(OnlyOnLeft) Right=Null(Null)", }; string[] actualMismatches = TestHelpers.StringFromMismatches(mismatches); Assert.False(match); Assert.True(actualMismatches.Length == expectedMismatches.Length); for (int index = 0; index < expectedMismatches.Length; index++) { Assert.Equal(expectedMismatches[index], actualMismatches[index]); } }
public void ComparePropertyThrows() { Element leftObject = new Element() { Content = new TypeWithPropertyThatThrows(), }; Element rightObject = new Element() { Content = new TypeWithPropertyThatThrows(), }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); TestHelpers.ObjectToConsole(leftObject, factory); Assert.True(match, "objects did not match"); }
public void CompareBasicTypesMinValues() { BasicTypes leftObject = new BasicTypes() { BoolPrimitive = false, BytePrimitive = byte.MinValue, CharValue = char.MinValue, DoublePrimitive = double.MinValue, FloatPrimitive = float.MinValue, IntPrimitive = int.MinValue, LongPrimitive = long.MinValue, ShortPrimitive = short.MinValue, StringPrimitive = "some string", TimeSpanValue = TimeSpan.MinValue, }; BasicTypes rightObject = new BasicTypes() { BoolPrimitive = true, BytePrimitive = byte.MaxValue, CharValue = char.MaxValue, DoublePrimitive = double.MaxValue, FloatPrimitive = float.MaxValue, IntPrimitive = int.MaxValue, LongPrimitive = long.MaxValue, ShortPrimitive = short.MaxValue, StringPrimitive = string.Empty, TimeSpanValue = TimeSpan.MaxValue, }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.False(match, "Basic types matched when they should not"); }
public void CompareObjectWithSharedNodes() { Element sharedLeftObject = new Element() { Name = "shared" }; Element leftObject = new Element() { Name = "RootElement", Content = new List <Element>() { sharedLeftObject, sharedLeftObject, }, }; Element sharedRightObject = new Element() { Name = "shared" }; Element rightObject = new Element() { Name = "RootElement", Content = new List <Element>() { sharedRightObject, sharedRightObject, }, }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "object with loop did not match"); }
public void ObjectGraphCodecExampleCodecCommentSampleRoundtrip() { var p1 = new Person("John"); p1.Children.Add(new Person("Peter")); p1.Children.Add(new Person("Mary")); var factory = new PublicPropertyObjectGraphFactory(); var graph1 = factory.CreateObjectGraph(p1); var stream = new MemoryStream(); var codec = new SimpleCodec(); codec.EncodeObjectGraph(graph1, stream); // Round trip original object graph graph1 = codec.DecodeObjectGraph(stream); var graph2 = codec.DecodeObjectGraph(stream); var result = new ObjectGraphComparer().Compare(graph1, graph2); Assert.True(result); }
public void TestSimpleClassHierarchy() { var leftObject = new Element() { Name = "root", Content = new Element() { Name = "element1", Content = new Element() { Name = "element2", } } }; var rightObject = new Element() { Name = "root", Content = new Element() { Name = "element1", Content = new Element() { Name = "element2", } } }; ObjectGraphFactory factory = new PublicPropertyObjectGraphFactory(); ObjectGraphComparer comparer = new ObjectGraphComparer(); var left = factory.CreateObjectGraph(leftObject); var right = factory.CreateObjectGraph(rightObject); bool match = comparer.Compare(left, right); Assert.True(match, "objects did not match"); }
public void XmlObjectGraphCodecEncodingCommentSample() { var actualStream = new MemoryStream(); var listener = new TextWriterTraceListener(actualStream); Trace.Listeners.Add(listener); // Example code starts here // var p1 = new Person("John"); p1.Children.Add(new Person("Peter")); p1.Children.Add(new Person("Mary")); // Create an object graph var factory = new PublicPropertyObjectGraphFactory(); var graph1 = factory.CreateObjectGraph(p1); // Encode a constructed object graph into XML var stream = new MemoryStream(); new XmlObjectGraphCodec().EncodeObjectGraph(graph1, stream); // Output the resulting XML into the Console window stream.Position = 0; using (var reader = new StreamReader(stream)) { Trace.WriteLine(reader.ReadToEnd()); } // Example code ends here // var expectedXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + @"<RootObject> <Name>John</Name> <Children> <Count>2</Count> <IEnumerable0> <Name>Peter</Name> <Children> <Count>0</Count> </Children> </IEnumerable0> <IEnumerable1> <Name>Mary</Name> <Children> <Count>0</Count> </Children> </IEnumerable1> </Children> </RootObject>"; // 'stream' is disposed, that is why we are using TraceListener Trace.Flush(); Trace.Listeners.Remove(listener); var actual = new XmlObjectGraphCodec().DecodeObjectGraph(actualStream); var expected = new XmlObjectGraphCodec().DecodeObjectGraph( new MemoryStream(Encoding.UTF8.GetBytes(expectedXml))); var result = new ObjectGraphComparer().Compare(actual, expected); Assert.True(result); }
public void CompareDifferentGraphsDifferentOrder() { var root1 = new GraphNode { Name = "RootNode" }; { var child1 = new GraphNode { Name = "Name", Parent = root1, ObjectValue = "Peter" }; var child4 = new GraphNode { Name = "Value", Parent = root1, ObjectValue = 3 }; // This node should be reported var child2 = new GraphNode { Name = "Value", Parent = root1 }; var child3 = new GraphNode { Name = "Value", Parent = root1 }; var child21 = new GraphNode { Name = "Grandchild", Parent = child2, ObjectValue = 1 }; root1.Children.Add(child1); root1.Children.Add(child4); root1.Children.Add(child2); root1.Children.Add(child3); child2.Children.Add(child21); } var root2 = new GraphNode { Name = "RootNode" }; { var child1 = new GraphNode { Name = "Name", Parent = root2, ObjectValue = "Peter" }; var child2 = new GraphNode { Name = "Value", Parent = root2 }; var child3 = new GraphNode { Name = "Value", Parent = root2 }; var child21 = new GraphNode { Name = "Grandchild", Parent = child2, ObjectValue = 1 }; var child22 = new GraphNode { Name = "Stranger", Parent = child2, ObjectValue = 1 }; // This node should be reported root2.Children.Add(child1); root2.Children.Add(child2); root2.Children.Add(child3); child2.Children.Add(child21); child2.Children.Add(child22); } IEnumerable <ObjectComparisonMismatch> mismatches; var result = new ObjectGraphComparer().Compare(root1, root2, out mismatches); Assert.False(result); var expected = new [] { "RightNodeHasFewerChildren:Left=RootNode(Null) Right=RootNode(Null)", "ObjectValuesDoNotMatch:Left=RootNode.Value(3) Right=RootNode.Value(Null)", "MissingLeftNode:Left=Null(Null) Right=RootNode.Value.Grandchild(1)", "MissingLeftNode:Left=Null(Null) Right=RootNode.Value.Stranger(1)", "MissingRightNode:Left=RootNode.Value(Null) Right=Null(Null)" }; var actual = TestHelpers.StringFromMismatches(mismatches); for (int i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], actual[i]); } }