Mockito: InvalidUseOfMatchersException

145

У меня есть инструмент командной строки, который выполняет проверку DNS. Если проверка DNS прошла успешно, команда переходит к дальнейшим задачам. Я пытаюсь написать для этого модульные тесты с помощью Mockito. Вот мой код:

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

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

Я использую InetAddressFactory, чтобы имитировать статическую реализацию InetAddressкласса. Вот код фабрики:

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

Вот мой пример модульного теста:

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

Исключение при выполнении testPostDnsCheck()теста:

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

Любые данные о том, как решить эту проблему?

деванг
источник

Ответы:

290

Сообщение об ошибке описывает решение. Линия

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

использует одно исходное значение и одно сопоставление, когда требуется использовать либо все исходные значения, либо все сопоставители. Правильная версия может читать

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))
Райан Стюарт
источник
8
Как глупо с моей стороны. Я продолжал анализировать, почему 2-й параметр продолжал давать мне ошибку. Спасибо за разъяснение. Я новичок в Mockito, это моя первая встреча.
Деванг
32

У меня уже долгое время была одна и та же проблема, мне часто приходилось смешивать сопоставители и значения, и мне никогда не удавалось сделать это с Mockito .... до недавнего времени! Я поместил решение здесь в надежде, что оно кому-то поможет, даже если этот пост довольно старый.

Очевидно, что в Mockito невозможно использовать Matcher AND значения вместе, но что, если есть Matcher, принимающий сравнение переменной? Это решило бы проблему ... а на самом деле есть: eq

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

В этом примере «метас» - это существующий список значений.

Сэм
источник
5
Потрясающие. org.mockito.Mockito.eq()
javaPlease42
4
правильный импорт теперь org.mockito.ArgumentMatchers.eq ()
sam
16

Это может помочь кому-то в будущем: Mockito не поддерживает насмешку над «финальными» методами (прямо сейчас). Это дало мне то же самое InvalidUseOfMatchersException.

Решение для меня заключалось в том, чтобы поместить часть метода, которая не должна быть «окончательной», в отдельный, доступный и переопределяемый метод.

Просмотрите API Mockito для вашего варианта использования.

delucasvb
источник
Это помогло понять, почему мой код kotlin выдает ошибку, потому что все методы в kotlin являются окончательными!
sorry_I_wont 02
Потрясающее спасибо
Майкл В.
0

Несмотря на использование всех сопоставителей, у меня возникла та же проблема:

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

Мне потребовалось немного времени, чтобы понять, что метод, который я пытался имитировать, был статическим методом класса (скажем, Xyz.class), который содержит только статический метод, и я забыл написать следующую строку:

PowerMockito.mockStatic(Xyz.class);

Возможно, это поможет другим, так как это также может быть причиной проблемы.

S Kumar
источник
0

В моем случае исключение было вызвано тем, что я пытался имитировать package-accessметод. Когда я изменил уровень доступа к методу из packageк protectedисключению ушло. Например, внутри класса Java,

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

метод String getName(String id)должен быть МИНИМУМ protected уровня, чтобы мог работать механизм насмешек (подклассы).

Shizhen
источник
-1

Не используйте Mockito.anyXXXX (). Непосредственно передайте значение параметру метода того же типа. Пример:

A expected = new A(10);

String firstId = "10w";
String secondId = "20s";
String product = "Test";
String type = "type2";
Mockito.when(service.getTestData(firstId, secondId, product,type)).thenReturn(expected);

public class A{
   int a ;
   public A(int a) {
      this.a = a;
   }
}
Динеш Кумар
источник