Comment vérifier qu'une méthode spécifique n'a pas été appelée à l'aide de Mockito?


627

Comment vérifier qu'une méthode n'est pas appelée sur la dépendance d'un objet?

Par exemple:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

Avec le test Foo:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}

Réponses:


1091

Encore plus significatif:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

La documentation de cette fonctionnalité est là §4 "Vérification du nombre exact d'appels / au moins x / jamais" , et le neverjavadoc est ici .


144
L'utilisation neverest la méthode la meilleure et la plus spécifique, mais si vous avez besoin de vérifier un objet factice entier, pensez également à verifyZeroInteractions(mockObject)ou verifyNoMoreInteractions(mockObject).
Jeff Bowman

que faire si someMethod est privé ??
Sumit Kumar Saha

1
Ensuite, vous ne pouvez pas vous moquer en premier lieu (avec Mockito);) PowerMock permet cela mais c'est plus complexe à configurer. Ou si vous êtes propriétaire du code, vous détendez la visibilité de l'emballage.
Brice

2
Depuis 3.0.1 verifyZeroInteractionsest obsolète. verifyNoInteractions est la suggestion d'une alternative. La version Mockito au moment de ce commentaire est le 3.3.3
VKB

109

utilisez le deuxième argument de la Mockito.verifyméthode, comme dans:

verify(dependency, Mockito.times(0)).someMethod()


11
VerificationMode public statique never () {temps de retour (0); }
gbero

3
never()n'est pas beaucoup plus lisible que times(0). Mais l'existence de neveraugmente la charge cognitive et rend le système mockito plus difficile à comprendre et à se rappeler comment l'utiliser. Donc, vraiment, mockito n'aurait pas dû inclure neverdans leur API, cela ne vaut pas le coût mental.
BT

Question: ce formulaire vérifie-t-il qu'il a someMethodété appelé 0 fois, ou vérifie-t-il seulement qu'il someMethodn'a jamais été appelé avec zéro argument?
BT

@BT - J'imagine qu'il vérifie que l' someMethodargument avec zéro a été appelé zéro fois - non vérifié.
beluchin

18

Comme modèle plus général à suivre, j'ai tendance à utiliser un @Afterbloc dans le test:

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Ensuite, le test est libre de vérifier uniquement ce qui doit être appelé.

De plus, j'ai constaté que j'oubliais souvent de vérifier s'il n'y avait pas d'interactions, pour découvrir plus tard que des choses étaient appelées qui n'auraient pas dû l'être.

Je trouve donc ce modèle utile pour intercepter tous les appels inattendus qui n'ont pas été spécifiquement vérifiés.


9
La documentation de Mockito indique que ce modèle ne doit pas être utilisé de manière abusive - "Un mot d'avertissement: certains utilisateurs qui ont fait beaucoup de moquerie classique, attendez-exécuter-vérifier ont tendance à utiliser verifyNoMoreInteractions () très souvent, même dans chaque méthode de test. VerifyNoMoreInteractions () n'est pas recommandé à utiliser dans toutes les méthodes de test. verifyNoMoreInteractions () est une assertion pratique de la boîte à outils de test d'interaction. N'utilisez-la que lorsque cela est pertinent. L'abus conduit à des tests sur-spécifiés et moins maintenables. " Voir ici
Chadi

2
"Utilisez-le uniquement lorsque cela est pertinent". Je pense que c'est toujours pertinent. Je ne vois pas ce schéma comme un abus: comme je l'ai dit, il constate que "des choses étaient appelées qui n'auraient pas dû être". Pour moi, c'est un élément de vérification essentiel: si quelque chose appelle un référentiel qu'il ne devrait pas utiliser, je veux le savoir! Sauf s'il existe un autre moyen de vérifier cela sans utiliser verifyNoMoreInteractions? Les autres réponses ici reposent sur le rédacteur du test qui se souvient explicitement de lister ces vérifications: c'est trop sujet aux erreurs dans mon livre.
David Lavender

2
J'ai vu ce commentaire, mais j'ai également senti que le raisonnement n'était pas convaincant. J'aimerais en savoir plus sur les raisons pour lesquelles ce n'est pas recommandé.
tobinibot

2
@tobinibot Parce que l'idée des tests unitaires est de vérifier un contrat. La plupart des contrats n'impliquent généralement pas combien de fois une autre méthode est invoquée, mais plutôt que la transmission de paramètres connus entraîne une réponse connue. En n'utilisant plus d'interactions, vous vérifiez essentiellement l'implémentation ligne par ligne, ce qui rend le refactoring et l'implémentation fastidieux. Ce qui n'est pas le but des tests unitaires.
Andrew T Finnell

8

Tout d'abord: vous devez toujours importer mockito static, de cette façon le code sera beaucoup plus lisible (et intuitif):

import static org.mockito.Mockito.*;

Il existe en fait de nombreuses façons d'y parvenir, mais il est (sans doute) plus propre d'utiliser le

verify(yourMock, times(0)).someMethod();

partout dans vos tests, lorsque sur d'autres tests vous l'utilisez pour affirmer un certain nombre d'exécutions comme ceci:

verify(yourMock, times(5)).someMethod();

Les alternatives sont:

verify(yourMock, never()).someMethod();

Alternativement - lorsque vous voulez vraiment vous assurer qu'un certain objet simulé n'est PAS appelé du tout - vous pouvez utiliser:

verifyZeroInteractions(yourMock)

7

Les méthodes verifyNoMoreInteractions()et verifyZeroInteractions()ont en interne la même implémentation que:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

nous pouvons donc utiliser n'importe lequel d'entre eux sur un objet fictif ou un tableau d'objets fictifs pour vérifier qu'aucune méthode n'a été appelée à l'aide d'objets fictifs.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.