Usando o método genérico “any()” do Mockito
-
21-09-2019 - |
Pergunta
Eu tenho uma interface com um método que espera um array 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 foi passado - "não me importo".
Como escrevo o seguinte código usando any()
, o método genérico, em vez de anyObject()
?
IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());
Solução
Desde o Java 8 você pode usar o método sem argumentos any
método e o argumento de tipo serão inferidos pelo compilador:
verify(bar).doStuff(any());
Explicação
A novidade no Java 8 é que o tipo de destino de uma expressão será usada 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âmetros de tipo (na maioria das vezes).
Neste caso o tipo de parâmetro de doStuff
será o tipo de destino para any()
, e o tipo de valor de retorno de any()
será escolhido para corresponder a esse tipo de argumento.
Tipos primitivos
Infelizmente, isso não funciona com tipos primitivos:
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 irá inferir Integer
como o valor de retorno de any()
.Mockito não estará ciente disso (devido ao apagamento de tipo) e retornará o valor padrão para tipos de referência, que é null
.O tempo de execução tentará desembalar o valor de retorno chamando o método intValue
método nele antes de passá-lo para doStuff
, e a exceção é lançada.
Outras dicas
Isso deve funcionar
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
verify(bar).DoStuff(any(Foo[].class));
Você pode usar Mockito.isA()
por 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)
Como eu precisava usar esse recurso para o meu projeto mais recente (em um ponto, atualizamos a partir de 1.10.19), apenas para manter os usuários (que já estão usando o Mockito-core versão 2.1.0 ou maior) atualizados, os métodos estáticos das respostas acima devem ser retirados de ArgumentMatchers
classe:
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;
Lembre -se disso se você planeja manter seus artefatos do Mockito atualizados como possivelmente começando na versão 3, essa classe pode não existir mais:
De acordo com 2.1.0 e acima, Javadoc de org.mockito.matchers afirma:
Usar
org.mockito.ArgumentMatchers
. Esta aula agora está presa para evitar um nome de nome com hamcrest *org.hamcrest.Matchers
classe. Esta classe provavelmente será removida na versão 3.0.