Korzystanie z ogólnej metody „any ()” Mockito


194

Mam interfejs z metodą, która oczekuje tablicy Foo:

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

Szydzę z tego interfejsu za pomocą Mockito i chciałbym to potwierdzić doStuff() jest on wywoływany, ale nie chcę sprawdzać poprawności przekazywanych argumentów - „nie przejmuj się”.

Jak napisać następujący kod za pomocą any()metody ogólnej zamiast anyObject()?

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

Odpowiedzi:


111

Od wersji Java 8 można używać metody bez argumentów any, a argument typu zostanie wyprowadzony przez kompilator:

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

Wyjaśnienie

Nowością w Javie 8 jest to, że docelowy typ wyrażenia będzie używany do wnioskowania o parametrach typu jego podwyrażeń. Przed Java 8 tylko argumenty metod były używane do wnioskowania o parametrach typu (przez większość czasu).

W takim przypadku typ parametru doStuffbędzie typem docelowym any(), a typ wartości zwracanej any()zostanie wybrany tak, aby pasował do tego typu argumentu.

Mechanizm ten został dodany w Javie 8 głównie w celu kompilacji wyrażeń lambda, ale ogólnie poprawia wnioskowania typu.


Typy pierwotne

To nie działa z typami pierwotnymi, niestety:

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

Problem polega na tym, że kompilator będzie wnioskować Integerjako wartość zwracana any(). Mockito nie będzie tego świadomy (z powodu kasowania typu) i zwróci domyślną wartość dla typów referencyjnych, tj null. Środowisko wykonawcze spróbuje rozpakować wartość zwracaną przez wywołanie intValuemetody przed przekazaniem jej doStuff, a wyjątek zostanie zgłoszony.


Jestem mile zaskoczony za każdym razem, gdy ta odpowiedź zyskuje aprobatę! Domyślam się, że pytanie to nie przyciągnie zbyt wiele uwagi od wersji Java 8, ponieważ anymetoda powinna po prostu działać. Nie szukasz odpowiedzi na rzeczy, które po prostu działają!
Lii

Przybyłem tu, ponieważ nie wiedziałem, dlaczego mój kod nie działa, any()ale było w porządku anyBoolean(), co pięknie pokazuje ostatnia część twojej odpowiedzi.
AdrienW

274

To powinno działać

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

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

31
na wypadek, gdyby ktoś tego potrzebował w Scali:verify(bar).DoStuff(any[Array[Foo]])
Tolitius

6
Miałem problem z importem, w imporcie korzystałem z any () z hamcrest i kolidował on z tym z mockito.
Doppelganger,

4
Proszę spojrzeć na API, argument klasy służy tylko do rzutowania, metoda wciąż akceptuje dowolny obiekt! site.mockito.org/mockito/docs/current/org/mockito/… . W tym przypadku użyj isA () site.mockito.org/mockito/docs/current/org/mockito/… .
thilko

1
Ta klasa jest teraz przestarzała, aby uniknąć konfliktu nazw z Hamcrestem. Użyj org.mockito.ArgumentMatchers
leo9r

12

Możesz użyć Mockito.isA()do tego:

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)


To jest poprawna odpowiedź. Używanie dowolnego (Clazz) jest całkowicie błędne.
Surasin Tancharoen

3
@SurasinTancharoen Właściwie każdy (Class) jest tylko aliasem isA (Class) (patrz dokumentacja). Więc to wcale nie jest źle.
jmiserez,

8

Ponieważ musiałem korzystać z tej funkcji w moim najnowszym projekcie (w pewnym momencie zaktualizowaliśmy wersję 1.10.19), po to tylko, aby użytkownicy (którzy już używają wersji mockito-core 2.1.0 lub nowszej ) byli na bieżąco, statycznie metody z powyższych odpowiedzi należy pobrać z ArgumentMatchersklasy:

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

Pamiętaj o tym, jeśli planujesz aktualizować swoje artefakty Mockito, ponieważ prawdopodobnie począwszy od wersji 3, ta klasa może już nie istnieć:

Zgodnie z 2.1.0 i nowszymi Javadoc z org.mockito.Matchers stwierdza:

Zastosowanie org.mockito.ArgumentMatchers. Ta klasa jest teraz przestarzała, aby uniknąć konfliktu nazw z klasą Hamcrest * org.hamcrest.Matchers . Ta klasa prawdopodobnie zostanie usunięta w wersji 3.0.

Napisałem mały artykuł na temat symboli wieloznacznych mockito, jeśli jesteś gotowy na dalsze czytanie.


Jak mogę zaimportować org.mockito.ArgumentMatcher do Scali? Próbowałem zaimportować org.mockito.ArgumentMatcher.any Otrzymuję błąd `wartość any any not a member of object org.mockito.ArgumentMatcher
Manu Chadha

Czy możesz mi powiedzieć, jaki jest odpowiednik w wersji 3.0?
Manu Chadha

Dowiemy się, kiedy zostanie wydany;)
Maciej Kowalski
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.