Какая разница между Mockito Matchers - это A, any, eq, и то же самое?

Меня смущает, в чем разница между ними, и какой выбрать в каком случае. Некоторая разница может быть очевидной, как any а также eqНо я включаю их всех просто чтобы быть уверенным.

Я удивляюсь их различиям, потому что я столкнулся с этой проблемой: у меня есть этот метод POST в классе Controller

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 класс) и вернуть 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 переопределено, вы увидите реализацию Object.equals по умолчанию, которая будет иметь то же поведение, что и same(obj),

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

  • Для Mockito 1.x используйте argThat с кастомным Hamcrest Matcher<T> который выбирает именно те объекты, которые вам нужны.
  • Для Mockito 2.0 и выше используйте Matchers.argThat с обычаем org.mockito.ArgumentMatcher<T>, или же MockitoHamcrest.argThat с кастомным Hamcrest Matcher<T>,

Если ваш Request.class реализует equals, тогда вы можете использовать eq():

Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...

Выше, когда будет активировать на

fooService.fooFxn(otherBar);

если

otherBar.equals(bar);

В качестве альтернативы, если вы хотите, чтобы макет работал для некоторого другого подмножества ввода (например, для всех баров с Bar.getBarLength()>10), вы можете создать Matcher. Я не вижу этот шаблон слишком часто, поэтому обычно я создаю Matcher как частный класс:

private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
  public boolean matches(Object otherBar){
     //Checks, casts, etc.
     return otherBar.getBarLength()>10;
  }
}

Затем вы использовали бы этот механизм сопоставления следующим образом:

when(fooService.fooFxn(argThat(new BarMatcher())).then...

Надеюсь, это поможет!

Другие вопросы по тегам