web-dev-qa-db-fra.com

Comment utiliser Mockito pour afficher toutes les invocations sur une maquette

J'ai un test unitaire qui échoue et je ne sais pas pourquoi. Je veux être en mesure de voir toutes les invocations sur la maquette qui se produisent dans le système à tester. Ce n'est pas toujours le comportement que je veux pour tous les tests, mais simplement pour un test que je dois modifier rapidement pour pouvoir déterminer ce qui ne va pas.

Cependant, cela ressemble un peu à un hack. Est-il possible de faire cela nativement dans Mockito, sans avoir à utiliser Thread.currentThread().getStackTrace()?

Ce n'est pas préférable, car la trace de la pile inclut tous les autres appels utilisés en interne par Mockito.

26
durron597

Cette fonctionnalité est intégrée depuis Mockito 1.9.5. Juste utiliser 

mock(ClassToMock.class, withSettings().verboseLogging())
41
MRalwasser

À partir de Mockito 1.9.5, vous pouvez inspecter une maquette avec MockingDetails Mockito.mockingDetails(Object mockToInspect) .

Vous pouvez soit Diguer dans les propriétés MockingDetails en appelant: getMock(), getStubbings(), getInvocations() et ainsi de suite ... ou simplement utiliser la méthode printInvocations() qui renvoie: 

une liste conviviale des invocations qui ont eu lieu avec l'objet fictif . De plus, cette méthode imprime les informations de stubbing, , Y compris les stubbings non utilisés. Pour plus d'informations sur la détection de stubbing Non utilisée, voir MockitoHint.

Par exemple avec JUnit 5: 

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    Foo foo;

    @Mock
    Bar bar;

    @Test
    void doThat() throws Exception {

        Mockito.when(bar.getValue())
               .thenReturn(1000L);          

        // ACTION
        foo.doThat();

        // ASSERTION
        // ...

        // add that to debug the bar mock           
        System.out.println(mockingDetails(bar).printInvocations());
    }
}

Et vous obtenez un résultat tel que:

 [Mockito] Interactions de: Mock for Bar, hashCode: 962287291 
 1. bar.getValue (); 
 -> at Foo.doThat () (Foo.Java:15 ) 
 - stubbed -> at FooTest.doThat (FooTest.Java:18) 

Notez que les classes avec une ligne référencée dans la sortie sont des liens vers votre classe de code/test source. Très pratique. 

2
davidxxx

J'ai pu déterminer une méthode qui utilise utilise Thread.currentThread().getStackTrace() et parcourt les éléments. C'est moche, mais ça fait le travail. J'espère qu'un autre répondeur aura une meilleure méthode.

  1. Créez une InvocationListener et transmettez-lui le nom de classe du système sous test.
  2. Transmettez l'auditeur dans Mockito.withSettings().invocationListeners()
  3. Modifiez temporairement le test pour créer le simulacre avec cet objet MockSettings.

Code de la InvocationListener:

public static class DebugInvocationListener implements
        InvocationListener {
    private final String className;

    public DebugInvocationListener(Class<?> klass) {
        this(klass.getName());
    }

    public DebugInvocationListener(String className) {
        this.className = className;
    }

    @Override
    public void reportInvocation(MethodInvocationReport report) {
        System.out.println(report.getInvocation());
        StackTraceElement[] trace = Thread.currentThread().getStackTrace();
        for(StackTraceElement element : trace) {
            if(element.getClassName().equals(className)) {
                System.out.println(element);
                System.out.println();
                break;
            }
        }
    }
}
0
durron597