Comment vérifier que cette méthode n'a PAS été appelée dans Moq?

466

Comment vérifier que cette méthode n'a PAS été appelée dans Moq ?

At-il quelque chose comme AssertWasNotCalled?

MISE À JOUR: à partir de la version 3.0, une nouvelle syntaxe peut être utilisée:

mock.Verify(foo => foo.Execute("ping"), Times.Never());
alex
la source

Réponses:

155

MISE À JOUR : Depuis la version 3, vérifiez la mise à jour de la question ci-dessus ou la réponse de Dann ci-dessous.

Soit, rendez votre maquette stricte afin qu'elle échoue si vous appelez une méthode pour laquelle vous n'avez aucune attente

new Mock<IMoq>(MockBehavior.Strict)

Ou, si vous voulez que votre maquette soit lâche, utilisez le .Throws (Exception)

var m = new Mock<IMoq>(MockBehavior.Loose);
m.Expect(a => a.moo()).Throws(new Exception("Shouldn't be called."));
Dan Fish
la source
9
... ou Callback () pour définir un indicateur qui peut être affirmé.
alex
2
De plus, avec l'option # 2, vous ne pouvez pas avoir un VerifyAll dans une méthode Teardown générale - il échouera en disant que l'attente n'a pas été satisfaite; quand le test devrait idéalement réussir.
Gishu
51
Ce n'est pas vraiment une "vérification non appelée" car elle pourrait être prise dans la méthode et fonctionnerait toujours - fournissant un faux positif!
Dan
4
Expect est désormais obsolète
Tomasz Sikora
5
Cela aurait pu être le meilleur moyen possible en 2009, mais certainement pas maintenant. désolé
Fabio Milheiro
537

Exécutez une vérification après le test qui a un Times.Neverensemble d'énumérations. par exemple

_mock.Object.DoSomething()
_mock.Verify(service => service.ShouldntBeCalled(),Times.Never());
Dan
la source
4
Ce qui est essentiel ici, c'est que l'appel Verify (action, Never) est après l'appel à la maquette. Je pensais qu'il mettait en place la vérification pour appeler VerifyAll () plus tard (ce qui ne fonctionne pas )
piers7
Simple et efficace. Merci.
Ian Grainger
45

Volé à: Réponse de John Foster à la question "Besoin d'aide pour mieux comprendre Moq"

L'une des choses que vous voudrez peut-être tester est que la méthode de rémunération n'est pas appelée lorsqu'une personne âgée de plus de 65 ans est transmise à la méthode

[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {

    var mockPensionService = new Mock<IPensionService>();

    var person = new Person("test", 66);

    var calc = new PensionCalculator(mockPensionService.Object);

    calc.PayPensionContribution(person);

    mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}
Chris Marisic
la source
10

Cela ne fonctionne pas dans les versions récentes de Moq (depuis au moins 3.1), cela devrait être spécifié dans la Verifyméthode comme mentionné dans la réponse.

En fait, il est préférable de spécifier .AtMost(0)après l'instruction Returns.

var m = new Mock<ISomething>();
m.Expect(x => x.Forbidden()).Returns("foo").AtMost(0);

Bien que le «jette» fonctionne également, AtMost(0)est plus expressif à mon humble avis.

miha
la source
-5

Utilisez .AtMostOnce ();

Après le vrai test, appelez à nouveau la méthode. S'il lève une exception, il a été appelé.

Aaron Digulla
la source
1
N'est-ce pas un peu trop obscur pour affirmer que l'exception a été levée par un framework moqueur?
alex
Pourquoi? Vérifiez simplement le type de l'exception. Si c'est l'un jeté mon Moq, vous êtes en sécurité.
Aaron Digulla
8
Utiliser Verify avec Times.Never n'est pas un meilleur choix ... Je suis d'accord avec alex que cette solution fonctionne, mais est certainement obscure.
Bip bip