85 votes

Puis-je retarder la réponse d'une méthode bloquée avec Mockito ?

Je suis en train d'écrire des tests unitaires. J'ai besoin de simuler une méthode à long terme avec Mockito pour tester la gestion du délai d'attente de mon implémentation. Est-ce possible avec Mockito ?

Voici ce qu'il en est :

when(mockedService.doSomething(a, b)).thenReturn(c).after(5000L);

100voto

K.L. Points 1766

Il suffit de mettre le fil en veilleuse pendant la durée souhaitée. Attention cependant - de telles choses peuvent vraiment ralentir l'exécution de vos tests automatisés, vous pourriez donc vouloir isoler ces tests dans une suite séparée.

Il ressemblerait à ceci :

when(mock.load("a")).thenAnswer(new Answer<String>() {
   @Override
   public String answer(InvocationOnMock invocation){
     Thread.sleep(5000);
     return "ABCD1234";
   }
});

54voto

Viswanath Points 1

De mockito 2.8.44, org.mockito.internal.stubbing.answers.AnswersWithDelay est disponible à cet effet. Voici un exemple d'utilisation

 doAnswer( new AnswersWithDelay( 1000,  new Returns("some-return-value")) ).when(myMock).myMockMethod();

18voto

Simon Ludwig Points 665

J'ai créé un utilitaire pour cela :

import java.time.Duration;
import java.util.concurrent.TimeUnit;

import static org.mockito.Mockito.doAnswer;

public class Stubber {

    public static org.mockito.stubbing.Stubber doSleep(Duration timeUnit) {
        return doAnswer(invocationOnMock -> {
            TimeUnit.MILLISECONDS.sleep(timeUnit.toMillis());
            return null;
        });
    }

    public static <E> org.mockito.stubbing.Stubber doSleep(Duration timeUnit, E ret) {
        return doAnswer(invocationOnMock -> {
            TimeUnit.MILLISECONDS.sleep(timeUnit.toMillis());
            return ret;
        });
    }

}

et dans votre scénario de test, utilisez simplement :

doSleep(Duration.ofSeconds(3)).when(mock).method(anyObject());

-1voto

Matej Lachman Points 21

Pour les tests unitaires, il est préférable de créer une méthode qui fait appel à l'actuel Thread.sleep(long l), puis de simuler cette méthode. Avec cela, vous pouvez injecter votre test avec un comportement génial qui fera que votre test pensera qu'il attend aussi longtemps que vous le souhaitez. Ainsi, vous pouvez exécuter un grand nombre de tests en un clin d'œil tout en testant différents scénarios liés au temps. Avant de l'utiliser, mon UnitTest durait six minutes. Maintenant, il dure moins de 200 ms.

public class TimeTools {
public long msSince(long msStart) {
    return ((System.nanoTime() / 1_000_000) - msStart);
}

public long msNow() {
    return (System.nanoTime() / 1_000_000);
}

public Boolean napTime(long msSleep) throws InterruptedException {
    Thread.sleep(msSleep);
    return true;
}
}
-----------------------------------
@Mock
TimeTools Timetools;

@TEST
public void timeTest() {
when(timeTools.msSince(anyLong()))
            .thenReturn(0l)
            .thenReturn(5_500l)
            .thenReturn(11_000l)
            .thenReturn(11_000l)
            .thenReturn(0l)
            .thenReturn(11_000l)
            .thenReturn(11_000l)
            .thenReturn(0l)
            .thenReturn(29_000l);
}

Mais la meilleure approche est d'injecter le sleeper et de le simuler. Ainsi, dans vos tests, vous ne dormirez pas réellement. Vos tests unitaires s'exécuteront alors aussi rapidement que l'éclair.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X