Como verificar se um método específico não foi chamado usando o Mockito?

625

Como verificar se um método não é chamado na dependência de um objeto?

Por exemplo:

public interface Dependency {
    void someMethod();
}

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

Com o teste 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??**
    }
}
beluchin
fonte

Respostas:

1087

Ainda mais significativo:

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

// ...

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

A documentação desse recurso está lá §4 "Verificando o número exato de chamadas / pelo menos x / nunca" , e o neverjavadoc está aqui .

Brice
fonte
144
Usar neveré a maneira melhor e mais específica, mas se você precisar verificar um objeto falso inteiro, considere também verifyZeroInteractions(mockObject)ou verifyNoMoreInteractions(mockObject).
Jeff Bowman
o que fazer se someMethod for privado ??
Sumit Kumar Saha
1
Então você não pode zombar dele em primeiro lugar (com Mockito);) O PowerMock permite isso, mas é mais complexo de configurar. Ou, se você possui o código, relaxa a visibilidade do pacote.
Brice
2
Desde 3.0.1 verifyZeroInteractionsfoi preterido. verifyNoInteractions é a alternativa sugerida. A versão do Mockito no momento deste comentário é 3.3.3
VKB
108

use o segundo argumento no Mockito.verifymétodo, como em:

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

beluchin
fonte
11
public VerificationMode estático never () {return times (0); }
gbero 25/04
3
never()não é significativamente mais legível que times(0). Mas a existência de neveraumenta a carga cognitiva e torna o sistema mockito mais difícil de entender e lembrar como usar. Então, o mockito realmente não deveria ter incluído neverem sua API, não vale o custo mental.
BT
Pergunta: este formulário verifica se someMethodfoi chamado 0 vezes ou apenas someMethodse nunca foi chamado com zero argumentos?
BT
@ BT - eu imagino que verifica o someMethodcom zero argumentos foi chamado zero vezes, não verificado.
precisa saber é
18

Como padrão mais geral a seguir, costumo usar um @Afterbloco no teste:

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

Em seguida, o teste é gratuito para verificar apenas o que deve ser chamado.

Além disso, descobri que muitas vezes esquecia de verificar "sem interações", apenas para descobrir mais tarde que estavam sendo chamadas coisas que não deveriam ter acontecido.

Portanto, acho esse padrão útil para capturar todas as chamadas inesperadas que não foram especificamente verificadas.

David Lavender
fonte
9
A documentação do Mockito afirma que esse padrão não deve ser abusado - "Uma palavra de aviso: alguns usuários que fizeram muita zombaria clássica, esperam executar verificam tendem a usar o VerifiqueNoMoreInteractions () com muita freqüência, mesmo em todos os métodos de teste. VerifiqueNoMoreInteractions () não é recomendado para uso em todos os métodos de teste. confirmNoMoreInteractions () é uma asserção útil do kit de ferramentas de teste de interação. Use-o apenas quando for relevante. O abuso de dados leva a testes superespecíficos e com menos manutenção. " Veja aqui
Chadi
2
"Use somente quando for relevante". Eu sinto que é sempre relevante. Não vejo esse padrão como abuso: como eu disse, descobre que "coisas estavam sendo chamadas que não deveriam ter sido". Para mim, essa é uma peça vital de verificação: se algo está chamando um repositório que não deveria estar usando, eu quero saber sobre isso! A menos que haja outra maneira de verificar isso sem usar verifyNoMoreInteractions? As outras respostas aqui se baseiam no autor do teste, lembrando-se explicitamente de listar essas verificações: isso é muito propenso a erros no meu livro.
David Lavender
2
Vi esse comentário, mas também senti que o raciocínio não era convincente. Gostaria de ler mais sobre por que isso não é recomendado.
usar o seguinte comando
2
@tobinibot Porque a ideia do teste de unidade é verificar um contrato. A maioria dos contratos normalmente não envolve quantas vezes é invocado outro método, mas a passagem de parâmetros conhecidos resulta em uma resposta conhecida. Ao não usar mais interações, você basicamente verifica a implementação linha por linha, o que torna a refatoração e a implementação tediosas. Qual não é o objetivo do teste de unidade.
Andrew T Finnell
8

Primeiro de tudo: você deve sempre importar mockito estático, assim o código será muito mais legível (e intuitivo):

import static org.mockito.Mockito.*;

Na verdade, existem muitas maneiras de conseguir isso, mas é (sem dúvida) mais limpo usar o

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

método em todos os seus testes, quando em outros testes você o usa para afirmar uma certa quantidade de execuções como esta:

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

As alternativas são:

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

Como alternativa - quando você realmente quer ter certeza de que um determinado objeto zombado NÃO é realmente chamado -, você pode usar:

verifyZeroInteractions(yourMock)
fl0w
fonte
7

O método verifyNoMoreInteractions()e verifyZeroInteractions()internamente têm a mesma implementação que:

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

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

portanto, podemos usar qualquer um deles em objetos simulados ou matriz de objetos simulados para verificar se nenhum método foi chamado usando objetos simulados.

Ujjwal
fonte