Mockito. Проверка аргументов метода

Я гуглил по этому поводу, но не нашел ничего актуального. У меня есть что-то вроде этого:

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);

Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();

Теперь я хочу убедиться, что mymethod(Object o), который вызывается из runtestmethod(), был вызван с Объектом o, а не любым другим. Но я всегда сдаю тест, независимо от того, что я проверяю, например, с помощью:

Mockito.verify(mock.mymethod(Mockito.eq(obj)));

или

Mockito.verify(mock.mymethod(Mockito.eq(null)));

или

Mockito.verify(mock.mymethod(Mockito.eq("something_else")));

Я всегда сдаю тест. Как я могу выполнить эту проверку (если это возможно)?

Спасибо.

Ответ 1

Альтернативой ArgumentMatcher является ArgumentCaptor.

Официальный пример:

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

Вывод также может быть определен с помощью аннотации @Captor:

@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
    //...
    verify(mock).doSomething(captor.capture());
    assertEquals("John", captor.getValue().getName());
}

Ответ 2

Вы пытаетесь сделать логическое равенство с использованием метода objectequals? Вы можете сделать это, используя аргумент argThat, который включен в Mockito

import static org.mockito.Matchers.argThat

Далее вы можете реализовать свой собственный аргумент, который будет относиться к каждому объекту .equals method

private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
    T thisObject;

    public ObjectEqualityArgumentMatcher(T thisObject) {
        this.thisObject = thisObject;
    }

    @Override
    public boolean matches(Object argument) {
        return thisObject.equals(argument);
    }
}

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

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);

Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();

verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));

Если вы просто собираетесь для ТОЧНОГО равенства (тот же объект в памяти), просто сделайте

verify(mock).mymethod(obj);

Это подтвердит, что он был вызван один раз.

Ответ 3

  • Вам не нужен помощник eq, если вы не используете других помощников.
  • Вы не используете правильный синтаксис - ваш вызов метода должен находиться вне .verify(mock). Теперь вы инициируете верификацию результата вызова метода, не проверяя ничего (не делая вызов метода). Следовательно, все тесты проходят.

Вы должны выглядеть так:

Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");

Ответ 4

Я использовал Mockito.verify таким образом

@UnitTest
public class JUnitServiceTest
{
    @Mock
    private MyCustomService myCustomService;


    @Test
    public void testVerifyMethod()
    {
       Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
       Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
       Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
       Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
       Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
       Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); //   no other method called except this
    }
}

Ответ 5

Вы проверили метод equals для класса mockable? Если этот возвращает всегда true или вы тестируете один и тот же экземпляр для одного и того же экземпляра, а метод equal не перезаписывается (и поэтому он проверяет только ссылки), он возвращает true.

Ответ 6

Другой метод заключается в использовании метода org.mockito.internal.matchers.Equals.Equals вместо его переопределения:

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));

Ответ 7

Вы пробовали его с тем же() совпадением? Как в:

verify(mockObj).someMethod(same(specificInstance));

У меня была та же проблема. Я попробовал его с помощью eq(), а также с помощником refEq(), но у меня всегда были ложные срабатывания. Когда я использовал тот же() совпадение, тест завершился неудачно, когда аргументы были разными экземплярами и переданы после того, как аргументы были одним и тем же экземпляром.

Ответ 8

вот как вы можете не подтвердить свой аргумент:

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

    ...
    verify(mock).mymethod(argThat(
                                  (x)->false
                                 ));

В вашем конкретном случае лучше использовать ArgumentMatcher.eq, поэтому ваше сообщение об ошибке будет гораздо более информативным, например: Argument(s) are different! Wanted: mock.mymethod(Object_o); Actual invocation has different arguments: mock.mymethod("SOME_OTHER_OBJECT");

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

    ...
    Object o = getObject();
    ...
    verify(mock).mymethod(
                        eq(o)
                        );

Ответ 9

Вы также можете использовать TypeSafeDiagnosingMatcher

    private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
    return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {

        StringBuilder text = new StringBuilder(500);

        @Override
        protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
            String productCode = req.getPackageIds().iterator().next().getValue();
            if (productCode.equals(request.getSupplierProductCode())) {
                text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
                return true;
            }

            text.append(req.toString());
            return false;
        }

        @Override
        public void describeTo(Description d) {
            d.appendText(text.toString());
        }
    };
}

Затем убедитесь, что вызов:

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));