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