Usando o método genérico “any ()” do Mockito

194

Eu tenho uma interface com um método que espera uma matriz de Foo:

public interface IBar {
  void doStuff(Foo[] arr);
}

Estou zombando dessa interface usando o Mockito e gostaria de afirmar que doStuff()é chamado, mas não quero validar qual argumento é passado - "não me importo".

Como escrevo o código a seguir usando any()o método genérico em vez de anyObject()?

IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());
ripper234
fonte

Respostas:

111

Desde o Java 8, você pode usar o anymétodo sem argumento e o argumento type será inferido pelo compilador:

verify(bar).doStuff(any());

Explicação

A novidade no Java 8 é que o tipo de destino de uma expressão será usado para inferir parâmetros de tipo de suas subexpressões. Antes do Java 8, apenas argumentos para métodos eram usados ​​para inferência de parâmetro de tipo (na maioria das vezes).

Nesse caso, o tipo de parâmetro de doStuffserá o tipo de destino any()e o tipo de valor de retorno any()será escolhido para corresponder a esse tipo de argumento.

Esse mecanismo foi adicionado no Java 8 principalmente para poder compilar expressões lambda, mas melhora as inferências de tipo em geral.


Tipos primitivos

Isso não funciona com tipos primitivos, infelizmente:

public interface IBar {
    void doPrimitiveStuff(int i);
}

verify(bar).doPrimitiveStuff(any()); // Compiles but throws NullPointerException
verify(bar).doPrimitiveStuff(anyInt()); // This is what you have to do instead

O problema é que o compilador inferirá Integercomo o valor de retorno de any(). O Mockito não estará ciente disso (devido ao apagamento do tipo) e retornará o valor padrão para os tipos de referência, que é null. O tempo de execução tentará desmarcar o valor de retorno chamando o intValuemétodo antes de passá-lo para doStuff, e a exceção será lançada.

Lii
fonte
Fico agradavelmente surpreendido toda vez que essa resposta é votada! Eu teria imaginado que a questão não atrairia muita atenção desde o Java 8, já que o anymétodo deveria funcionar. Você não procura respostas para coisas que simplesmente funcionam!
Lii
Eu vim aqui porque não sabia por que meu código não funcionava, any()mas estava bem anyBoolean(), com a qual a última parte da sua resposta esclarece lindamente.
AdrienW
274

Isso deve funcionar

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;

verify(bar).DoStuff(any(Foo[].class));
nervosismo
fonte
31
apenas no caso de alguém precisar em Scala:verify(bar).DoStuff(any[Array[Foo]])
tolitius
6
Eu tive um problema com a importação, estava usando o any () do hamcrest nas minhas importações e ele colidiu com o do mockito.
Doppelganger
4
Por favor, dê uma olhada na API, o argumento de classe é usado apenas para fundição, o método ainda aceita qualquer tipo de objeto! site.mockito.org/mockito/docs/current/org/mockito/… . Use isA () para este caso site.mockito.org/mockito/docs/current/org/mockito/… .
Thilko 31/08/2015
1
Esta classe está agora obsoleta para evitar um conflito de nome com o Hamcrest. Use org.mockito.ArgumentMatchers
leo9r 22/03/19
12

Você pode usar Mockito.isA()para isso:

import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;

verify(bar).doStuff(isA(Foo[].class));

http://site.mockito.org/mockito/docs/current/org/mockito/Matchers.html#isA(java.lang.Class)

thilko
fonte
Essa é a resposta correta. Usar qualquer um (Clazz) está completamente errado.
Surasin Tancharoen
3
@SurasinTancharoen Na verdade, any (Class) é apenas um alias de isA (Class) (consulte os documentos). Portanto, não está nada errado.
jmiserez
8

Como eu precisava usar esse recurso para o meu projeto mais recente (a certa altura atualizamos a partir de 1.10.19), apenas para manter os usuários (que já estão usando a versão 2.1.0 ou superior do mockito-core ) atualizados, o static Os métodos das respostas acima devem ser retirados da ArgumentMatchersclasse:

import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;

Lembre-se disso se você planeja manter seus artefatos do Mockito atualizados, pois possivelmente a partir da versão 3, essa classe pode não existir mais:

Conforme 2.1.0 e acima, o Javadoc do org.mockito.Matchers declara:

Use org.mockito.ArgumentMatchers. Esta classe está agora obsoleta para evitar um conflito de nome com a org.hamcrest.Matchers classe Hamcrest * . Essa classe provavelmente será removida na versão 3.0.

Eu escrevi um pequeno artigo sobre curingas mockito se você quiser ler mais.

Maciej Kowalski
fonte
Como posso importar org.mockito.ArgumentMatcher no Scala? Eu tentei importar org.mockito.ArgumentMatcher.any Eu recebo o erro `value any não é membro do objeto org.mockito.ArgumentMatcher
Manu Chadha
Você poderia me dizer qual é o equivalente na versão 3.0?
Manu Chadha
Saberemos, uma vez que será lançado;)
Maciej Kowalski