Mockito: InvalidUseOfMatchersException

141

Mam narzędzie wiersza poleceń, które wykonuje sprawdzenie DNS. Jeśli sprawdzenie DNS powiedzie się, polecenie przechodzi do dalszych zadań. Próbuję napisać testy jednostkowe do tego za pomocą Mockito. Oto mój kod:

public class Command() {
    // ....
    void runCommand() {
        // ..
        dnsCheck(hostname, new InetAddressFactory());
        // ..
        // do other stuff after dnsCheck
    }

    void dnsCheck(String hostname, InetAddressFactory factory) {
        // calls to verify hostname
    }
}

Używam InetAddressFactory do mockowania statycznej implementacji InetAddressklasy. Oto kod fabryczny:

public class InetAddressFactory {
    public InetAddress getByName(String host) throws UnknownHostException {
        return InetAddress.getByName(host);
    }
}

Oto mój przypadek testowy:

@RunWith(MockitoJUnitRunner.class)
public class CmdTest {

    // many functional tests for dnsCheck

    // here's the piece of code that is failing
    // in this test I want to test the rest of the code (i.e. after dnsCheck)
    @Test
    void testPostDnsCheck() {
        final Cmd cmd = spy(new Cmd());

        // this line does not work, and it throws the exception below:
        // tried using (InetAddressFactory) anyObject()
        doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class));
        cmd.runCommand();
    }
}

Wyjątek dotyczący przeprowadzania testPostDnsCheck()testu:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

Masz jakieś uwagi, jak rozwiązać ten problem?

devang
źródło

Odpowiedzi:

283

Komunikat o błędzie przedstawia rozwiązanie. Linia

doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class))

używa jednej wartości surowej i jednego dopasowania, gdy wymagane jest użycie wszystkich wartości surowych lub wszystkich dopasowań. Prawidłowa wersja może czytać

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))
Ryan Stewart
źródło
8
Ale głuptas ze mnie. Ciągle analizowałem, dlaczego drugi parametr ciągle dawał mi błąd. Dzięki za wytłumaczenie. Jestem bardzo nowy w Mockito, to moje pierwsze spotkanie.
devang
32

Miałem ten sam problem od dłuższego czasu, często potrzebowałem mieszać Matcherów i wartości i nigdy nie udało mi się tego zrobić z Mockito… aż do niedawna! Umieściłem tutaj rozwiązanie, mając nadzieję, że komuś pomoże, nawet jeśli ten post jest dość stary.

Oczywiście nie jest możliwe jednoczesne użycie dopasowań ORAZ wartości w Mockito, ale co by było, gdyby dopasowujący zaakceptował porównanie zmiennej? To rozwiązałoby problem ... i faktycznie jest: eq

when(recommendedAccessor.searchRecommendedHolidaysProduct(eq(metas), any(List.class), any(HotelsBoardBasisType.class), any(Config.class)))
            .thenReturn(recommendedResults);

W tym przykładzie „metas” to istniejąca lista wartości

sam
źródło
5
Niesamowite. org.mockito.Mockito.eq()
javaPlease42
4
prawidłowy import to teraz org.mockito.ArgumentMatchers.eq ()
sam
15

Może to komuś pomóc w przyszłości: Mockito nie obsługuje kpiny z „ostatecznych” metod (w tej chwili). Dało mi to samo InvalidUseOfMatchersException.

Rozwiązaniem dla mnie było umieszczenie części metody, która nie musiała być „ostateczna”, w oddzielnej, dostępnej i nadającej się do zastąpienia metodzie.

Przejrzyj interfejs API Mockito pod kątem swojego przypadku użycia.

delucasvb
źródło
Pomogło to w ustaleniu, dlaczego mój kod kotlin dał mi błąd, ponieważ wszystkie metody w kotlin są ostateczne!
sorry_I_wont
0

Pomimo korzystania ze wszystkich dopasowań otrzymałem ten sam problem:

"org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
1 matchers expected, 3 recorded:"

Zajęło mi trochę czasu, zanim zrozumiałem, że metoda, którą próbowałem wyszydzić, była metodą statyczną klasy (powiedzmy Xyz.class), która zawiera tylko metodę statyczną i zapomniałem napisać następujący wiersz:

PowerMockito.mockStatic(Xyz.class);

Być może pomoże to innym, ponieważ może być również przyczyną problemu.

S Kumar
źródło
0

W moim przypadku wyjątek został zgłoszony, ponieważ próbowałem kpić z package-accessmetody. Kiedy zmienił poziom dostępu z metody packagedo protectedwyjątek odszedł. Np. Wewnątrz poniżej klasy Java,

public class Foo {
    String getName(String id) {
        return mMap.get(id);
    }
}

metoda String getName(String id)musi być na NAJMNIEJSZYM protected poziomie, aby mechanizm kpiny (podklasy) działał.

shizhen
źródło