How to combine collection and ownership statements with flowing statements?

I would like to "combine" the assertions and assertions of the Fluent Assertion collection, for example. argue that two IEnumerable are pairwise equal, using a property by property (possibly "nested") comparison (ie, structural equality, in the language of a functional language).

Specific example:

 var dic = new Dictionary<int, string>() { {1, "hi"}, {2, "bye" } }; var actual = dic.ToSelectListItems(0).OrderBy(si => si.Text); var expected = new List<SelectListItem>() { new SelectListItem() {Selected = false, Text="bye", Value="2"}, new SelectListItem() {Selected = false, Text="hi", Value="1"} }; 

Here I wrote a ToSelectListItems extension method that converts a Dictionary to IEnumerable from SelectListItem (from ASP.NET MVC). I want to argue that actual and expected "structurally" equal, noting that the reference type SelectListItem does not override Equal and therefore uses reference equality by default.

Update

The following manual solution is currently being used, still hoping for something better built into FluentAssertions:

 public static void ShouldBeStructurallyEqualTo<T, U>(this IEnumerable<T> actual, IEnumerable<U> expected) { actual.Should().HaveCount(expected.Count()); actual.Zip(expected).ForEach(pair => pair.Item1.ShouldHave().AllProperties().IncludingNestedObjects().EqualTo(pair.Item2)); } 

(note: Zip is my own IEnumerable extension, which uses Tuple.Create as the default projection)

Update 2

Here are two minimal examples:

 public class FooBar { public string Foo { get; set; } public int Bar { get; set; } } public class TestClass { [Test] public void MinimalExample() { List<FooBar> enumerable1 = new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } }; List<FooBar> enumerable2 = new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } }; enumerable1.ShouldHave().SharedProperties().IncludingNestedObjects().EqualTo(enumerable2); //Test 'TestClass.MinimalExample' failed: System.Reflection.TargetParameterCountException : Parameter count mismatch. // at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) // at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) // at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) // at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index) // at FluentAssertions.Assertions.PropertyEqualityValidator.AssertSelectedPropertiesAreEqual(Object subject, Object expected) // at FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker tracker, String parentPropertyName) // at FluentAssertions.Assertions.PropertyEqualityValidator.Validate() // at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject, String reason, Object[] reasonArgs) // at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject) // MiscAssertions.cs(32,0): at TestClass.MinimalExample() } [Test] public void MinimalExample2() { IEnumerable<FooBar> enumerable1 = (new List<FooBar>() { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } }).Cast<FooBar>(); FooBar[] enumerable2 = new [] { new FooBar() { Foo = "x", Bar = 1 }, new FooBar() { Foo = "y", Bar = 2 } }; enumerable1.ShouldHave().SharedProperties().IncludingNestedObjects().EqualTo(enumerable2); //Test 'TestClass.MinimalExample2' failed: System.InvalidOperationException : Please specify some properties to include in the comparison. // at FluentAssertions.Assertions.PropertyEqualityValidator.Validate(UniqueObjectTracker tracker, String parentPropertyName) // at FluentAssertions.Assertions.PropertyEqualityValidator.Validate() // at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject, String reason, Object[] reasonArgs) // at FluentAssertions.Assertions.PropertyAssertions`1.EqualTo(Object otherObject) // MiscAssertions.cs(52,0): at TestClass.MinimalExample2() } } 
+8
c # unit-testing nunit fluent-assertions
source share
2 answers

I have added support for your script to the main Fluent Assertions branch. It will be part of the next version, but it may take a month or two to accumulate enough changes to guarantee another release. If you want, you can grab the source assembly and run release.bat to create an intermediate version.

+6
source share

If I interpret your question correctly, I think you should try version 1.7.0 of the free claims. In this version, we have changed the behavior that when using IncludingNestedObjects will also do this in collections of objects. Excerpt from the documentation.

"In addition, you can conduct a structural comparison at a level further by including the IncludingNestedObjects property in it. This will instruct you to compare all (collections) of complex types that are related to the properties of the object (in this example). By default, it will state that nested object properties correspond to the nested properties of the expected object. However, if you specify SharedProperties, it will only compare the same properties between nested objects. For example:

dto.ShouldHave().SharedProperties().IncludingNestedObjects.EqualTo(customer); "

+7
source share

All Articles