2009-08-25 8 views
4

Je voudrais savoir s'il existe un moyen de comparer deux objets dans MBUnit afin que le test soit passé lorsque les objets "semblent" identiques, même s'il s'agit d'instances distinctes?MbUnit: Comparaison d'instances d'objets distincts

Par exemple:

[TestFixture] 
class ComparisonTestFixture 
{ 

    class foo 
     { 
      public string bar; 
     } 

    [Test] 
    public void ComparisonTest() 
    { 

     foo foo1 = new foo() 
      { 
       bar = "baz" 
      }; 

     foo foo2 = new foo() 
      { 
       bar = "baz" 
      }; 


     //This assertion should be successful, but it isn't 
     //*** Failures *** 
     //Expected values to be equal. 
     //Expected Value & Actual Value : {foo: bar = "zzz...."} 
     //Remark : Both values look the same when formatted but they are distinct instances. 
     Assert.AreEqual(foo1,foo2); 
    } 
} 

Assert.AreEqual() ne fonctionne pas pour ce (test échoue, voir ci-dessus le code source). Puisqu'il remarque que "Les deux valeurs se ressemblent quand elles sont formatées mais qu'elles sont des instances distinctes", je pense qu'il doit y avoir un moyen de le faire dans MbUnit sans sérialiser les objets dans XML dans mon propre code.

Dois-je écrire ma propre méthode d'extension Assert pour cela?

Répondre

1

Je vous suggère de remplacer la méthode Equals sur votre classe pour effectuer la comparaison souhaitée. Cela vous permet de définir l'égalité des valeurs au lieu de l'égalité de référence. Une mise en garde est que vous devez également remplacer GetHashCode si vous remplacez Equals pour vous assurer que deux objets égaux renvoient également le même code de hachage. Voici un exemple très simple;

public class Foo { 

    public String Bar { 
    get; 
    set; 
    } 

    public String Baz { 
    get; 
    set; 
    } 

    public override Boolean Equals(Object other) { 
    Foo otherFoo = other as Foo; 
    return otherFoo != null 
     && Bar.Equals(otherFoo.Bar) 
     && Baz.Equals(otherFoo.Baz); 
    } 

    public override Int32 GetHashCode() { 
    return Bar.GetHashCode()^Baz.GetHasCode(); 
    } 

} 

Si vous ne voulez pas passer outre Equals et vous voulez vraiment juste pour comparer des cas bien par bien, vous pouvez utiliser la réflexion:

public static Boolean AreEqual<T>(T a, T b) { 
    foreach (PropertyInfo propertyInfo in typeof(T).GetProperties()) 
    if (!Object.Equals(propertyInfo.GetValue(a, null), 
         propertyInfo.GetValue(b, null))) 
     return false; 
    return true; 
} 
+0

Mais ce ne serait pas générique. Je devrais le faire pour chaque nouvelle classe que je suis en train de tester. –

+0

Mais apparemment, vous classes utilise l'égalité des valeurs et non l'égalité de référence. Pour capturer ce fait, vous devriez vraiment envisager de remplacer 'Equals'. Cela pourrait non seulement profiter à vos tests mais aussi à votre code d'application. –

+0

Dans mon application actuelle, je n'ai pas besoin de comparer deux instances de ce type d'objet. Si je devais remplacer Equals, ce serait uniquement pour les tests unitaires. J'aime garder au minimum les codes généraux pour les tests unitaires. –

4

Il y a une overload of Assert.AreEqual() qui prend un IEqualityComparer<T> en tant que paramètre et une autre qui prend un EqualityComparison<T>

Sinon, vous pouvez utiliser Assert.AreEqual(Assert.XmlSerialize(a), Assert.XmlSerialize(b))

+0

Oui, mais où est l'avantage? Je devrais encore implémenter mon propre objet EqualityComparioson. Je ne vois aucun avantage à surcharger les égales ou à ajouter une méthode d'extension à Assert. –

+0

J'ai ajouté une autre option –

+0

La deuxième option est ce que j'ai essayé aussi.Cela fonctionne bien dans la plupart des cas, mais la sérialisation échoue pour certains objets en raison de l'utilisation de Ninject dans les coulisses. C'est ce qui m'a fait commencer ce fil. –

7

Yann a également implémenté un StructuralEqualityComparer qui compare les valeurs de propriétés une à une en fonction d'un ensemble de lambdas pour chaque propriété. Ça vaut le coup d'oeil.

Plus d'infos ici: http://www.gallio.org/api/html/T_MbUnit_Framework_StructuralEqualityComparer_1.htm

+0

Yup. Comme le dit Jeff, le comparateur d'égalité structurelle est le bon outil à utiliser dans ce cas. Plusieurs assertions acceptent un objet IEqualityComparer sont le paramètre (AreEqual, AreElementsEqual, etc.) le comparateur spécifie à l'assertion comment comparer les types qui ne sont pas explicitement équitables. Assert.AreEqual (foo1, foo2, new StructuralEqualityComparer {{x => x.bar}}); –

+0

Vous pouvez également trouver un exemple d'utilisation simple ici: http://interfacingreality.blogspot.com/2009/06/assertdistinct-in-mbunit-v3.html –

+0

Cela semble bien, mais un peu exagéré pour ce que j'essaie d'atteindre. Je vais utiliser un EqualityComparer avec reflexction à la place. Encore, merci pour l'indice! –

1

Ce que je habituellement est juste le mettre en œuvre ToString() override - qui est considéré comme le meilleur une meilleure pratique de le faire de toute façon.

donc dans votre cas:

public override string ToString() 
{ 
    return string.Format("Class foo, bar={0}",bar); 
} 

alors votre AreEqual(foo1,foo2) sera fait rapport des résultats corrects car il suffit d'appeler le ToString par défaut la mise en œuvre

+0

Cela fonctionne, mais il a le même inconvénient que de surcharger Equals. Ce n'est pas générique, mais nécessite un code supplémentaire pour chaque nouveau type d'objet qui doit être comparé. –