web-dev-qa-db-fra.com

Utilisation de Verify pour confirmer les valeurs de paramètres attendues dans la classe de simulation Moq

J'essaie de vérifier qu'une méthode dans une maquette est appelée avec un paramètre d'objet attendu. J'utilise Moq, nUnit et je pense que la ressemblance d'AutoFixture devrait faire le travail. Vous trouverez ci-dessous une version simplifiée de ce que j'essaie de faire.

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

Remplacer Equals dans la classe A pour comparer les valeurs des propriétés et changer la ligne Verify en:

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

passe, mais je préfère ne pas remplacer 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
        }
    }
}
45
jaminto

Dans le Verify Moq vérifie par défaut l'égalité des références pour les arguments, donc il ne passe que lorsque vous fournissez les mêmes instances (sauf si vous avez remplacé Equals) dans vos tests et dans votre implémentation.

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 le Moq's It.Is construire pour tester correctement ceci sans remplacer Equals (en fait, pour cela, vous n'avez pas besoin du tout d'Autofixture):

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 manuellement les vérifications d'eqaulity pour toutes les propriétés.

70
nemesv

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

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

Voici la méthode de test d'origine, modifiée pour utiliser le proxy de 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 qu'il rend également l'assertion de test beaucoup plus spécifique que l'acceptation de toute instance .

Vous pouvez trouver plus de détails sur cette nouvelle fonctionnalité ici .

5
Nikos Baxevanis