Подтвердить что ты не робот

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

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

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

public Response doSomething(@ResponseBody Request request) {
    return someService.doSomething(request);
}

И хотел бы выполнить unit test на этом контроллере. У меня две версии. Первый из них простой, как этот

@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, но все они терпят неудачу.

Спасибо заранее. Надеюсь, я хорошо себя объяснил.

4b9b3361

Ответ 1

  • any() абсолютно ничего не проверяет. В Mockito 1.x, any(T.class) также абсолютно ничего не проверяет, а также сохраняет вас приложением (до Java 8).

    Это связано с изменениями в Mockito 2.0 и более поздних версиях, когда any(T.class) будет делиться семантикой isA, означающей "any 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>.

Ответ 2

Если ваш 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...

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