JavaRush/Курсы/JSP & Servlets/Вызовы mock-методов с параметрами

Вызовы mock-методов с параметрами

Открыта

4.1 Параметры методов

Предыдущие правила добавленные мок-объекту касались методов без параметров. А как создавать правила для методов с параметрами? Более того, хотелось бы создавать правила, чтобы при одних значениях параметров был один результат, а при других – другой.

Так тоже можно делать. Если вы хотите, чтобы при определенном параметре метод возвращал что-то определенное, то правило можно записать так:

Mockito.doReturn(результат).when(объект).имяМетода(параметр);

И сразу рассмотрим пример, чтобы лучше все понять. Пусть наш List возвращает имя Иван при запросе 10-го элемента, и имя Марья при запросе 500-го. Сказано – сделано.

@ExtendWith(MockitoExtension.class)
class ParamsTest {
 @Mock
 List mockList;

 @Test
    public void whenMockAnnotation() {
        //добавление первого правила
        Mockito.doReturn("Иван").when(mockList).get(10);
        //добавление второго правила
        Mockito.doReturn("Марья").when(mockList).get(500);

        assertEquals("Иван", mockList.get(10));
        assertEquals("Марья", mockList.get(500));

    }
}

4.2 Шаблоны параметров

И сразу хитрые коллеги зададут мне вопрос: “А как быть, если метод требует аргументы, но при любых значениях должен возвращать один и тот же результат?”. Не будем же мы писать:

Mockito.doReturn("Иван").when(mockList).get(1);
Mockito.doReturn("Иван").when(mockList).get(2);
Mockito.doReturn("Иван").when(mockList).get(99);

Нет, никто тебя так писать не заставляет. Если ты хочешь добавить правило mock-объекту, которое действует для метода с любыми аргументами, то для этого есть специальный объект:

Mockito.any()

Наш пример с его помощью будет записан так:

Mockito.doReturn("Иван").when(mockList).get(any(int.class));

Есть тут пара нюансов. Объект Mockito.any() имеет тип Object, поэтому для параметров разных типов есть его аналоги:

Метод Тип параметра
1 any() Object, включая null
2 any(ClassName.class) ClassName
3 anyInt() int
4 anyBoolean() boolean
5 anyDouble() double
6 anyList() List

Более корректно наш пример будет выглядеть так:

Mockito.doReturn("Иван").when(mockList).get(anyInt());

4.3 Метод doAnswer()

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

Для этого есть специальный метод – doAnswer(), в который передается функция, которая делает то, что тебе нужно:

Mockito.doAnswer(функция).when(объект).имяМетода(параметр);

Давай заставим метод get() класса List возвращать квадрат переданного ему аргумента. И напишем такую программу:

@ExtendWith(MockitoExtension.class)
class DoAnswerTest {
 @Mock
 List mockList;

 @Test
    public void whenMockAnnotation() {
        Mockito.doAnswer(invocation -> {
            int parameter = invocation.getArgument(0);
            return parameter * parameter;
        }).when(mockList).get(anyInt());

        assertEquals(100, mockList.get(10));
        assertEquals(25, mockList.get(5));
    }
}

Функцию мы задали с помощью объект класса Answer.

Комментарии (16)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Underdante
Уровень 74
10 августа, 17:03
а если тестируемый метод возвращает воид?
Мая
Уровень 82
14 октября 2025, 18:26
а почему мы в методе invocation.getArgument(0) подставляем 0, когда у нас не 0, а 10 и 5?
9 августа, 18:22
getArgument(0) это возврат первого аргумента метода значит
rwnmei
Уровень 57
28 августа 2025, 18:44
Прикольно все понятно
Артем Java Developer
13 февраля 2025, 11:02
Мы добрались до сложного поведения виртуальных методов. Теперь пора писать тесты на тесты😁
Арсений
Уровень 65
23 декабря 2023, 17:51
Павел
Уровень 19
Expert
18 декабря 2023, 16:07
Не понял в лекции: int.class это mock на примитивный тип данных int?
Олег
Уровень 79
Expert
3 декабря 2023, 18:41
И сразу рассмотрим пример, чтобы лучше все понять. Пусть наш List возвращает имя Иван при запросе 10-го элемента, и имя Марья при запросе 500-го. Сказано – сделано. Такие тесты работает как наша экономика с экрана ТВ. Намолотили, выпустили, прирост ВВП на душу населения, какую задачу поставили, то в эфир вылили, а какая истинная картина пофиг..... Так и эти тесты... Там может всё на перекосяк пошло, а они показывают всё Ок!!! Искусственные они какие то...
11 июля 2024, 12:49
так моки про искусвенность и есть, это в самом начале говорится. Предположим у вас есть серверная часть отдельно и клиентская отдельно, тестируем клиентскую, сервер должен что то возвращать для того чтобы тестируемый метод отрабатывал как надо, и вот класс-коннектор к серверу как раз и мокается, чтобы что то возвращал ожидаемое от сервера, а не дергать сервер каждый раз, тем более его может и не быть
Redya Daniel
Уровень 16
25 февраля 2023, 04:39
Не понял этого момента. Какого типа у нас invocation?
Mockito.doAnswer(invocation -> {
            int parameter = invocation.getArgument(0);
            return parameter * parameter;
        }).when(mockList).get(anyInt());
jvatechsBackend Developer в Ищу стажировкуExpert
16 мая 2023, 21:53
Я так понял это лямбда-выражение исходит из переопределения метода answer(InvocationOnMock invocation) интерфейса Answer, т.е. создается анонимный класс. По-иному это можно переписать так:
Mockito.doAnswer(new Answer<Integer>() {
    @Override
    public Integer answer(InvocationOnMock invocation) {
        int parameter = invocation.getArgument(0);
        return parameter * parameter;
    }
}).when(mockList).get(anyInt());
про InvocationOnMock invocation нашел следующее: При использовании Mockito InvocationOnMockобъект автоматически создается фреймворком при вызове фиктивного метода. Он представляет собой вызов метода и содержит такую ​​информацию, как аргументы метода, фиктивный объект и другие сведения. В предоставленном фрагменте кода invocationOnMockэто имя, данное автоматически созданному InvocationOnMockобъекту в answer()методе. Он не создается вами, а скорее передается в качестве параметра метода фреймворком Mockito при вызове фиктивного метода. Таким образом, несмотря на то, что InvocationOnMockэто интерфейс, вы все равно можете получить доступ к его методам и свойствам через автоматически созданный объект, предоставляемый инфраструктурой Mockito.
Anonymous #1384518
Уровень 35
Expert
3 августа 2023, 20:40
В Intellij есть удобная фишка. Можно после нужного вызова метода или переменной поставить .var далее tab и он сгенерирует результат в переменную с типом. Очень помогает в стримах, где непонятно какой тип возвращается. После просмотра, можно вернуть назад ctrl+z
СергейРаботает в ITQ-GroupExpert
1 октября 2022, 16:21
Вместо
Mockito.doReturn("Иван").when(mockList.get(any(int.class)));
Mockito.doReturn("Иван").when(mockList.get(anyInt());
Нужно писать так:
Mockito.doReturn("Иван").when(mockList).get(any(int.class));
Mockito.doReturn("Иван").when(mockList).get(anyInt());
Иначе будет:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at MockitoTest.doReturnStringListWhenAnySizeList(MockitoTest.java:101)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
Stas S
Уровень 108
Expert
8 сентября 2022, 08:15
Оба примера упадут с UnfinishedStubbingException и не потому, что там не хватает круглой скобки :) Правильно писать так :
Mockito.doAnswer(функция).when(объект).имяМетода(параметр);