Comment combiner les assertions de collection et de propriété à l'aide d'assertions fluides ?

StackOverflow https://stackoverflow.com/questions/9006820

Question

Je voudrais "combiner" les assertions de collection et les assertions de propriété de Fluent Assertion, par ex.affirmer que deux IEnumerablesont égaux par paire en utilisant une comparaison propriété par propriété (éventuellement "imbriquée") (c'est-à-direégalité structurelle, dans le langage fonctionnel).

Exemple concret :

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"}
};

Ici, j'ai écrit une méthode d'extension ToSelectListItems qui convertit un Dictionary à un IEnumerable de SelectListItems (à partir d'ASP.NET MVC).Je veux affirmer que actual et expected sont "structurellement" égaux, notant que le type de référence SelectListItem ne remplace pas Equals et utilise donc l'égalité de référence par défaut.

Mise à jour

J'utilise actuellement la solution suivante, élaborée à la main, en espérant toujours quelque chose de mieux intégré à 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 voici le mien IEnumerable extension qui utilise Tuple.Create comme projection par défaut)

Mise à jour 2

Voici deux exemples minimaux :

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()
    }
}
Était-ce utile?

La solution

J'ai ajouté la prise en charge de votre scénario dans la branche principale de Fluent Assertions.Il fera partie de la prochaine version, mais cela pourrait nous prendre un mois ou deux pour accumuler suffisamment de modifications pour justifier une autre version.Si vous le souhaitez, vous pouvez récupérer la version source et exécuter release.bat pour créer une version intermédiaire.

Autres conseils

Si j'interprète correctement votre question, je pense que vous devriez essayer la version 1.7.0 d'affirmations fluides.Dans cette version, nous avons modifié le comportement : lorsque l'outil IncludeNestedObjects est utilisé, il le fera également sur les collections d'objets.Un extrait de la documentation.

"De plus, vous pouvez pousser la comparaison structurelle un niveau plus loin en incluant la propriété IncludeNestedObjects.Cela demandera à la comparaison de comparer tous les (collections de) types complexes auxquels les propriétés du sujet (dans cet exemple) font référence.Par défaut, il affirmera que les propriétés imbriquées du sujet correspondent aux propriétés imbriquées de l'objet attendu.Toutefois, si vous spécifiez SharedProperties, il comparera uniquement les propriétés de même nom entre les objets imbriqués.Par exemple:

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top