Utilizzando il metodo generico "any ()" di Mockito


194

Ho un'interfaccia con un metodo che prevede una matrice di Foo:

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

Sto deridendo questa interfaccia usando Mockito, e vorrei affermare che doStuff()viene chiamato, ma non voglio confermare quale argomento viene passato - "non importa".

Come posso scrivere il seguente codice usando any(), il metodo generico, invece di anyObject()?

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

Risposte:


111

Da Java 8 è possibile utilizzare il anymetodo senza argomenti e l'argomento type verrà dedotto dal compilatore:

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

Spiegazione

La novità di Java 8 è che il tipo di destinazione di un'espressione verrà utilizzato per inferire i parametri di tipo delle sue sottoespressioni. Prima di Java 8 solo argomenti per i metodi usati per l'inferenza dei parametri di tipo (il più delle volte).

In questo caso il tipo di parametro di doStuffsarà il tipo di destinazione per any()e il tipo di valore restituito di any()verrà scelto in modo che corrisponda a quel tipo di argomento.

Questo meccanismo è stato aggiunto in Java 8 principalmente per essere in grado di compilare espressioni lambda, ma migliora generalmente le inferenze di tipo.


Tipi primitivi

Questo non funziona con i tipi primitivi, sfortunatamente:

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

Il problema è che il compilatore inferirà Integercome valore di ritorno di any(). Mockito non ne sarà a conoscenza (a causa della cancellazione del tipo) e restituirà il valore predefinito per i tipi di riferimento, ovvero null. Il runtime proverà a decomprimere il valore restituito chiamando il intValuemetodo su di esso prima di passarlo a doStuffe verrà generata l'eccezione.


Sono piacevolmente sorpreso ogni volta che questa risposta ottiene un voto! Avrei immaginato che la domanda non avrebbe attirato molta attenzione da Java 8, poiché il anymetodo dovrebbe funzionare. Non cerchi risposta per cose che funzionano e basta!
Lii,

Sono venuto qui perché non sapevo perché il mio codice non funzionasse, any()ma andava bene anyBoolean(), con cui l'ultima parte della tua risposta mette in luce magnificamente.
AdrienW,

274

Questo dovrebbe funzionare

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

verify(bar).DoStuff(any(Foo[].class));

31
nel caso in cui qualcuno ne abbia bisogno a Scala:verify(bar).DoStuff(any[Array[Foo]])
tolitius,

6
Ho avuto un problema con l'importazione, stavo usando any () da hamcrest nelle mie importazioni e si è scontrato con quello di mockito.
Doppelganger,

4
Dai un'occhiata all'API, l'argomento di classe è appena usato per il casting, il metodo accetta ancora qualsiasi tipo di oggetto! site.mockito.org/mockito/docs/current/org/mockito/… . Utilizzare isA () per questo caso site.mockito.org/mockito/docs/current/org/mockito/… .
thilko,

1
Questa classe è ora obsoleta per evitare uno scontro di nomi con Hamcrest. Usa org.mockito.ArgumentMatchers
leo9r

12

Puoi usare Mockito.isA()per quello:

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)


Questa è la risposta corretta L'uso di qualsiasi (Clazz) è completamente sbagliato.
Surasin Tancharoen,

3
@SurasinTancharoen In realtà, qualsiasi (Classe) è solo un alias di isA (Classe) (consultare la documentazione). Quindi non è affatto sbagliato.
jmiserez,

8

Dato che avevo bisogno di usare questa funzione per il mio ultimo progetto (a un certo punto abbiamo aggiornato dall'1.10.19), solo per mantenere aggiornati gli utenti (che stanno già utilizzando la versione mockito-core 2.1.0 o successiva ), i dati statici i metodi dalle risposte sopra dovrebbero essere presi dalla ArgumentMatchersclasse:

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

Tienilo a mente se stai pianificando di mantenere aggiornati i tuoi manufatti Mockito poiché probabilmente a partire dalla versione 3, questa classe potrebbe non esistere più:

Secondo la 2.1.0 e successive, Javadoc di org.mockito.Matchers afferma:

Usa org.mockito.ArgumentMatchers. Questa classe è ora obsoleta per evitare uno scontro di nomi con la org.hamcrest.Matchers classe Hamcrest * . Questa classe verrà probabilmente rimossa nella versione 3.0.

Ho scritto un piccolo articolo sui caratteri jolly mockito se sei pronto per ulteriori letture.


Come posso importare org.mockito.ArgumentMatcher in Scala? Ho provato import org.mockito.ArgumentMatcher.any ottengo un errore `valore any non è un membro dell'oggetto org.mockito.ArgumentMatcher
Manu Chadha

Potresti dirmi qual è l'equivalente nella versione 3.0?
Manu Chadha,

Lo sapremo una volta che verrà rilasciato;)
Maciej Kowalski il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.