2012-01-16 3 views
30

J'essaie de vérifier qu'une méthode dans un mock est appelée avec un paramètre d'objet attendu. J'utilise Moq, nUnit, et je pense que l'apparence d'AutoFixture devrait faire le travail. Voici une version simplifiée de ce que j'essaie de faire.Utilisation de Verify pour confirmer les valeurs de paramètres attendues dans Moq Mock classe

Existe-t-il un moyen de faire cela avec AutoFixture? Existe-t-il un meilleur moyen de vérifier que Something est appelée avec le paramètre approprié?

Redéfinition Equals dans la classe A pour comparer les valeurs de propriété et de modifier la Verify ligne:

barMock.Verify(m => m.Something(a)); 

passe, mais je préfère ne pas surcharger les méthodes equals dans chaque classe comme A dans mon projet.

namespace Test 
{ 
    using Moq; 
    using NUnit.Framework; 
    using Ploeh.SemanticComparison.Fluent; 

    public class A 
    { 
     public int P1 { get; set; } 
    } 
    public interface IBar 
    { 
     void Something(A a); 
    } 

    public class Foo 
    { 
     public A Data { get; private set; } 
     public void DoSomethingWith(IBar bar) 
     { 
      Data = new A { P1 = 1 }; 
      bar.Something(Data); 
     } 
    } 

    [TestFixture] 
    public class AutoFixtureTest 
    { 
     [Test] 
     public void TestSample() 
     { 
      var foo = new Foo(); 
      var barMock = new Mock<IBar>(); 
      var a = new A { P1 = 1 }; 
      var expectedA = a.AsSource().OfLikeness<A>(); 

      foo.DoSomethingWith(barMock.Object); 

      expectedA.ShouldEqual(foo.Data); // passes 
      barMock.Verify(m => m.Something(expectedA.Value)); // fails 
     } 
    } 
} 

Répondre

45

Dans le Verify Moq par des contrôles par défaut la référence pour l'égalité des arguments il ne passe que lorsque vous fournissez les mêmes instances (sauf si vous avez outrepassée Equals) dans vos tests et dans votre mise en œuvre.

Dans votre cas le expectedA.Value renvoie simplement le new A { P1 = 1 } créé dans le test qui n'est bien sûr pas la même instance créée dans DoSomethingWith.

Vous devez utiliser It.Is de Moq construction pour tester correctement ce sans écraser Equals (en fait pour cela, vous n'avez pas besoin Autofixture du tout):

barMock.Verify(m => m.Something(It.Is<A>(arg => arg.P1 == a.P1))); 

Mais si vous avez plusieurs propriétés comme P1, P2 , P3 ... AutoFixture peut être utile:

barMock.Verify(m => m.Something(It.Is<A>(arg => expectedA.Equals(a)))); 

Parce que vous n'avez pas besoin d'écrire les chèques de eqaulity manuellement pour toutes les propriétés.

+2

+1 En particulier, la dernière solution est l'approche correcte avec la ressemblance. FWIW il y a un élément de travail pour une nouvelle fonctionnalité pour Likeness pour lui permettre d'émettre de façon dynamique un proxy qui écrase Equals, ce qui simplifierait grandement la syntaxe ci-dessus: http://autofixture.codeplex.com/workitem/4230 –

+0

C'est fait, merci ! – jaminto

5

Si vous effectuez une mise à niveau vers AutoFixture 2.9.1 (ou plus récent), vous pouvez appeler la méthode CreateProxy sur l'instance Likeness qui émettra un proxy dynamique pour le type de destination.

Le proxy dynamique généré remplace Equals en utilisant Likeness, ce qui simplifie la syntaxe (pas mal).

Voici la méthode d'essai d'origine, modifié pour utiliser le proxy Ressemblance:

[Test] 
public void TestSample() 
{ 
    var foo = new Foo(); 
    var barMock = new Mock<IBar>(); 
    var expected = new A().AsSource().OfLikeness<A>().CreateProxy(); 
    expected.P1 = 1; 

    foo.DoSomethingWith(barMock.Object); 

    Assert.True(expected.Equals(foo.Data));  // passes 
    barMock.Verify(m => m.Something(expected)); // passes 
} 

Notez que cela fait aussi l'affirmation de test beaucoup plus précis que d'accepter Toute instance.

Vous trouverez plus de détails sur cette nouvelle fonctionnalité here.

Questions connexes