Eu tenho um teste JUnit que quero esperar por um período de tempo, de forma síncrona. Meu teste JUnit se parece com isto:
@Test
public void testExipres(){
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
//WAIT FOR 2 SECONDS
assertNull(sco.getIfNotExipred("foo"));
}
Eu tentei Thread.currentThread (). Wait (), mas ele lança uma IllegalMonitorStateException (conforme o esperado). Existe algum truque para isso ou eu preciso de um monitor diferente?
java
junit
thread-safety
Kylar
fonte
fonte
Thread.sleep
dizer algo como Usar Thread.sleep em um teste geralmente é uma má ideia. Ele cria testes frágeis que podem falhar de forma imprevisível, dependendo do ambiente ("Passa na minha máquina!") Ou da carga. Não confie no tempo (use mocks) ou use bibliotecas como Awaitility para testes assíncronos.Thread.sleep () pode funcionar na maioria dos casos, mas geralmente se você estiver esperando, está na verdade esperando que uma condição ou estado específico ocorra. Thread.sleep () não garante que tudo o que você está esperando realmente aconteceu.
Se você está esperando por uma solicitação de descanso, por exemplo, talvez ele retorne em 5 segundos, mas se você definir seu sono para 5 segundos no dia em que sua solicitação voltar em 10 segundos, seu teste irá falhar.
Para remediar isso, JayWay tem um ótimo utilitário chamado Awatility, que é perfeito para garantir que uma condição específica ocorra antes de você seguir em frente.
Tem uma boa API fluente também
https://github.com/jayway/awaitility
fonte
No caso do seu analisador de código estático (como SonarQube) reclamar, mas você não conseguir pensar em outra maneira, ao invés de dormir, você pode tentar um hack como:
Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);
É conceitualmente incorreto, mas é o mesmo queThread.sleep(1000)
.A melhor maneira, claro, é passar um Callable, com sua condição apropriada, ao invés do
true
que eu tenho.https://github.com/awaitility/awaitility
fonte
Duration
classe, mas desde a versão 4 eles a renomearam paraDurations
.Você pode usar a biblioteca java.util.concurrent.TimeUnit que usa Thread.sleep internamente. A sintaxe deve ser semelhante a esta:
Esta biblioteca fornece uma interpretação mais clara para a unidade de tempo. Você pode usar 'HOURS' / 'MINUTES' / 'SECONDS'.
fonte
sleep()
afetará o thread de trabalho?Você também pode usar o
CountDownLatch
objeto conforme explicado aqui .fonte
Há um problema geral: é difícil zombar do tempo. Além disso, é uma prática muito ruim colocar código de longa execução / espera em um teste de unidade.
Portanto, para tornar uma API de agendamento testável, usei uma interface com uma implementação real e uma simulação como esta:
Com isso, você pode imitar o tempo em seu teste:
Um mock avançado multi-threading para
Clock
é muito mais complexo, é claro, mas você pode fazer isso comThreadLocal
referências e uma boa estratégia de sincronização de tempo, por exemplo.fonte