InvalidUseOfMatchersException с mockito с использованием сопоставителей

Я работаю с mockito, и я получаю следующую проблему:

java.lang.AssertionError: 
Expected: (an instance of java.lang.IllegalArgumentException and exception with message a string containing "")
     but: an instance of java.lang.IllegalArgumentException <org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at com.rccl.middleware.kidsclub.engine.services.KidServiceTest.saveKid_kidExist_throwException(KidServiceTest.java:97)

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

Это мой тестовый код:

    @Mock
    private KidRepository kidRepository;

    @Mock
    private RoomService roomService;

    @Test
    public void saveKid_kidExist_throwException() {
        given(kidRepository.existsById(anyString())).willReturn(true);
        given(roomService.existShipRoomDefault()).willReturn(true);

        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage(startsWith("Kid already registered"));
        KidDTO kidDTO = MockDTO.buildKidDTO();

        service.saveKid(kidDTO);

        then(kidRepository).should().existsById(anyString());
    }

Это код метода saveKid, который в основном отправляет исключения:

       if (!validateShipRoomExist()) {
            log.warn("::: The ShipRoom document doesn't exist.");
            throw new RoomNotFoundException(NO_ROOMS_IN_DATABASE);
        }

        if (validateKidAlreadyRegistered(kidDTO.getId())) {
            log.warn("::: Trying to persist a Kid already persisted with ID [{}]", kidDTO.getId());
            throw new IllegalArgumentException(String.format("Kid already registered with ID [%s]", kidDTO.getId()));
        }

И это методы, называемые:

        private boolean validateShipRoomExist() {
            return roomService.existShipRoomDefault();
        }

        public boolean validateKidAlreadyRegistered(@NotNull String kidId) {
            return kidRepository.existsById(kidId);
        }

Далее мой код в roomService:

public boolean existShipRoomDefault() {
        return roomRepository.existsById(DEFAULT_AGGREGATOR_ID);
 }

Проблема в этом методе, у которого есть проблема, хотя я использую строку anyString() в этом тесте. Я не понимаю, что происходит в этом случае. Интересно, что в режиме отладки тест не завершается ошибкой, если у меня есть точка останова.


person rasilvap    schedule 11.09.2019    source источник
comment
хорошо, я предположил то же самое, но мне нужно оценить сообщение об ошибке, есть ли другой способ? Спасибо.   -  person rasilvap    schedule 12.09.2019
comment
kidto - это новый объект, созданный с помощью информации в классе MockDTO, это то, что вы имеете в виду?   -  person rasilvap    schedule 12.09.2019
comment
Э-э, какой тип expectedException. И что then(kidRepository).should().existsById(anyString()); должен делать?   -  person GhostCat    schedule 12.09.2019
comment
@GhostCat: я полагаю, это ExpectedException и строка предполагается, что это проверка метода existsById. Но он недоступен из-за того, как работает обработка исключений.   -  person second    schedule 12.09.2019


Ответы (1)


BDDMockito.startsWith — это метод Matcher, который вы использовали в expectedException.expectMessage, который не имеет отношения к насмешкам.

Если вы хотите оценить сообщение об исключении, вы должны сравнить его с полным сообщением.

Скорректированный тест может выглядеть так:

@Test
public void saveKid_kidExist_throwException() {

    // ...

    KidDTO kidDto = new KidDTO();
    kidDto.setId("1");

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage("Kid already registered with ID [1]");
    service.saveKid(kidDto);
}

Поскольку я не знаю, что делает класс MockDTO, и полагаю, что легко создать экземпляр KidDTO самостоятельно, я просто делаю это в приведенном выше примере.

Альтернативой было бы - в случае, если kidDTO является макетом - определить:

BDDMockito.given(kidDto.getId()).willReturn("1");
person second    schedule 12.09.2019