web-dev-qa-db-fra.com

Mockito - comment vérifier qu'une maquette n'a jamais été invoquée

Je cherche un moyen de vérifier avec Mockito, qu'il n'y a pas eu d'interaction avec une maquette donnée lors d'un test. C'est facile à réaliser pour une méthode donnée avec le mode de vérification never(), mais je n'ai pas encore trouvé de solution pour la maquette complète.

Ce que je veux réellement réaliser: vérifier dans les tests, que rien n'est imprimé sur la console. L'idée générale avec jUnit va comme ça:

private PrintStream systemOut;

@Before
public void setUp() {
    // spy on System.out
    systemOut = spy(System.out);
}

@After
public void tearDown() {
    verify(systemOut, never());  // <-- that doesn't work, just shows the intention
}

Un PrintStream a des tonnes de méthodes et je ne veux vraiment pas vérifier chacune avec une vérification distincte - et la même chose pour System.err ...

J'espère donc, s'il existe une solution simple, que je peux, étant donné que j'ai une bonne couverture de test, forcer les ingénieurs logiciels (et moi-même) à supprimer leur (mon) code de débogage comme System.out.println("Breakpoint#1"); ou e.printStacktrace(); avant de valider les modifications.

49
Andreas_D

Utilisez ceci :

import static org.mockito.Mockito.verifyZeroInteractions;

// ...

private PrintStream backup = System.out;

@Before
public void setUp() {
    System.setOut(mock(PrintStream.class));
}

@After
public void tearDown() {
    verifyZeroInteractions(System.out);
    System.setOut(backup);
}
63
gontard
verifyZeroInteractions(systemOut);

Comme indiqué dans les commentaires, cela ne fonctionne pas avec un espion.

Pour une réponse à peu près équivalente mais plus complète, voir la réponse de gontard à cette question.

11
Don Roby

Vous pouvez essayer une approche légèrement différente:

private PrintStream stdout;

@Before public void before() {
    stdout = System.out;
    OutputStream out = new OutputStream() {
        @Override public void write(int arg0) throws IOException {
            throw new RuntimeException("Not allowed");
        }
    };
    System.setOut(new PrintStream(out));
}

@After public void after() {
    System.setOut(stdout);
}

Si vous préférez, vous pouvez changer le type anonyme pour une maquette et vérifier comme le suggère Don Roby .

4
McDowell

Une façon de résoudre ce problème consiste à refactoriser la classe que vous testez, pour permettre l'injection d'un PrintStream qui peut être utilisé pour la sortie. Cela vous permettra de le tester à l'unité, sans vous fier au comportement de la classe System. Vous pouvez utiliser un constructeur package-private pour cette injection, car vous ne l'utiliserez que depuis la classe de test correspondante. Cela pourrait donc ressembler à ceci.

public class MyClass{
    private PrintWriter systemOut;

    public MyClass(){
        this(System.out);
    }

    MyClass(PrintWriter systemOut){
        this.systemOut = systemOut;

        // ...any other initialisation processing that you need to do
    }
}

et dans la classe elle-même, utilisez la variable systemOut au lieu de System.out partout où vous appelez cette dernière.

Maintenant, dans la classe de test, créez un mock PrintStream, et passez-le au constructeur package-private, pour obtenir l'objet que vous allez tester. Vous pouvez maintenant exécuter toutes les actions que vous souhaitez à partir de vos tests et utiliser verify pour vérifier leurs effets sur votre maquette PrintStream.

2
Dawood ibn Kareem