В чем разница между Mockito Matchers isA, any, eq и тем же?
меня смущает то, что разница между ними и какой из них выбрать в случае чего. Какая-то разница может быть очевидной, например any
и eq
, но я включаю их все, чтобы быть уверенным.
я задаюсь вопросом об их различиях, потому что я столкнулся с этой проблемой: У меня есть этот метод POST в классе контроллера
public Response doSomething(@ResponseBody Request request) {
return someService.doSomething(request);
}
и хотел бы выполнить модульный тест на этом контроллере. У меня две версии. Первый из них простой, как это
@Test
public void testDoSomething() {
//initialize ObjectMapper mapper
//initialize Request req and Response res
when(someServiceMock.doSomething(req)).thenReturn(res);
Response actualRes = someController.doSomething(req);
assertThat(actualRes, is(res));
}
но я хотел использовать подход MockMvc, как этот
@Test
public void testDoSomething() {
//initialize ObjectMapper mapper
//initialize Request req and Response res
when(someServiceMock.doSomething(any(Request.class))).thenReturn(res);
mockMvc.perform(post("/do/something")
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(req))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$message", is("done")));
}
оба работают хорошо. Но я хотел моего someServiceMock.doSomething()
в подходе MockMvc для получения req
, или, по крайней мере, объект, который имеет те же значения переменных в качестве req
(не просто Request
класс), и return res
, как и первый. Я знаю, что невозможно использовать подход MockMvc (или это так?), потому что объект, переданный в фактическом вызове, всегда отличается от объекта прошел в макете. Могу ли я достичь этого? Или это вообще имеет смысл? Или я должен быть удовлетворен, используя any(Request.class)
? Я пытался eq
, same
, но все они терпят неудачу.
спасибо заранее. Надеюсь, я хорошо объяснился.
2 ответов
-
any()
абсолютно ничего не проверяет. В Mockito 1.x,any(T.class)
также проверяет абсолютно ничего, но также сохраняет вас (до Java 8).это связано с изменением в Mockito 2.0 и за пределы, когда
any(T.class)
поделитьсяisA
семантика означает " любойT
" или правильно "любой экземпляр типаT
".any()
все равно ничего не проверит. isA(T.class)
проверяет, что аргументinstanceof T
, подразумевается, что он не является нулевым.same(obj)
проверяет, что аргумент является тем же экземпляром,obj
, таких, чтоarg == obj
- это правда.-
eq(obj)
проверяет, что аргумент равенobj
по егоequals
метод. Это также поведение, если вы передаете реальные значения без использования сопоставителей.обратите внимание, что если
equals
переопределено, вы увидите объект по умолчанию.равная реализация, которая будет иметь такое же поведение, какsame(obj)
.
Если вам нужна более точная настройка, вы можете использовать адаптер для своего собственного предиката:
- Для Mockito 1.x, Используйте
argThat
с пользовательским HamcrestMatcher<T>
это выбирает именно те объекты, которые вам нужны. - для Mockito 2.0 и за его пределами используйте
Matchers.argThat
с пользовательскимorg.mockito.ArgumentMatcher<T>
илиMockitoHamcrest.argThat
с пользовательским HamcrestMatcher<T>
.
если ваш запрос.класс реализует equals, тогда вы можете использовать eq ():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
выше , когда активировать на
fooService.fooFxn(otherBar);
если
otherBar.equals(bar);
альтернативно, если вы хотите, чтобы макет работал для некоторого другого подмножества ввода (например, все бары с баром.getBarLength ()>10), вы можете создать Сопоставитель. Я не вижу этот шаблон слишком часто, поэтому обычно я создаю сопоставление как частный класс:
private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
public boolean matches(Object otherBar){
//Checks, casts, etc.
return otherBar.getBarLength()>10;
}
}
вы бы тогда используйте этот matcher следующим образом:
when(fooService.fooFxn(argThat(new BarMatcher())).then...
надеюсь, что это поможет!