Mockito: InvalidUseOfMatchersException

140

Eu tenho uma ferramenta de linha de comando que executa uma verificação de DNS. Se a verificação do DNS for bem-sucedida, o comando continuará com outras tarefas. Estou tentando escrever testes de unidade para isso usando o Mockito. Aqui está o meu código:

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

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

Estou usando o InetAddressFactory para simular uma implementação estática da InetAddressclasse. Aqui está o código da fábrica:

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

Aqui está o meu caso de teste de unidade:

@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();
    }
}

Exceção ao executar o testPostDnsCheck()teste:

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"));

Alguma contribuição sobre como resolver isso?

devang
fonte

Respostas:

283

A mensagem de erro descreve a solução. A linha

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

usa um valor bruto e um correspondente, quando é necessário usar todos os valores brutos ou todos os correspondentes. Uma versão correta pode ler

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))
Ryan Stewart
fonte
8
Que bobo da minha parte. Continuei analisando por que o segundo parâmetro continuava me dando o erro. Obrigado por esclarecer. Sou muito novo em Mockito, este é o meu primeiro encontro.
Devang
32

Eu tinha o mesmo problema há muito tempo, muitas vezes precisava misturar Matchers e valores e nunca consegui fazer isso com o Mockito .... até recentemente! Coloquei a solução aqui esperando que ajude alguém, mesmo que este post seja bastante antigo.

Claramente, não é possível usar os Matchers AND valores juntos no Mockito, mas e se houvesse um Matcher aceitando comparar uma variável? Isso resolveria o problema ... e de fato existe: eq

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

Neste exemplo 'metas' é uma lista existente de valores

sam
fonte
5
Impressionante. org.mockito.Mockito.eq()
usar o seguinte código
4
a importação adequada agora é org.mockito.ArgumentMatchers.eq ()
sam
15

Pode ajudar alguém no futuro: Mockito não suporta zombar de métodos 'finais' (agora). Isso me deu o mesmo InvalidUseOfMatchersException.

A solução para mim foi colocar a parte do método que não precisava ser 'final' em um método separado, acessível e substituível.

Revise a API do Mockito para o seu caso de uso.

delucasvb
fonte
Isso ajudou a descobrir por que meu código kotlin me daria erro, porque todos os métodos no kotlin são finais!
sorry_I_wont
0

Apesar de usar todos os matchers, estava recebendo o mesmo problema:

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

Demorei um pouco para descobrir que o método que eu estava tentando zombar era um método estático de uma classe (por exemplo, Xyz.class) que contém apenas o método estático e eu esqueci de escrever a seguinte linha:

PowerMockito.mockStatic(Xyz.class);

Pode ser que isso ajude outras pessoas, pois também pode ser a causa do problema.

S Kumar
fonte
0

No meu caso, a exceção foi levantada porque tentei zombar de um package-accessmétodo. Quando mudei o nível de acesso do método de packagepara protecteda exceção foi embora. Por exemplo, dentro da classe Java,

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

o método String getName(String id)deve estar no protected nível MÍNIMO para que o mecanismo de zombaria (subclasse) possa funcionar.

shizhen
fonte