Java for Beginner
675 subscribers
548 photos
155 videos
12 files
839 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Всё о thenReturn, thenThrow и thenAnswer в Mockito

Когда создаются моки с помощью Mockito, вы можете настроить их поведение через методы when и then.... Эти методы позволяют указать, что должен вернуть мок-объект или как он должен себя вести при вызове его методов.

1. thenReturn

thenReturn задаёт значение, которое метод мока должен возвращать при вызове. Это самый простой способ настройки поведения.


Пример:
List<String> mockList = Mockito.mock(List.class);

// Настраиваем поведение метода
Mockito.when(mockList.get(0)).thenReturn("MockedValue");

// Проверяем
System.out.println(mockList.get(0)); // Выведет: MockedValue
System.out.println(mockList.get(1)); // Выведет: null (по умолчанию)


Особенности:
Может возвращать один и тот же результат для любого вызова.
Если метод вызывается с аргументом, для которого не задано поведение, возвращается значение по умолчанию (например, null для объектов, 0 для чисел).


Множественные возвраты:
Вы можете задать несколько возвратов, которые будут использоваться последовательно:
Mockito.when(mockList.get(0))
.thenReturn("FirstCall")
.thenReturn("SecondCall");

System.out.println(mockList.get(0)); // Выведет: FirstCall
System.out.println(mockList.get(0)); // Выведет: SecondCall
System.out.println(mockList.get(0)); // Выведет: SecondCall (последний возврат повторяется)


Когда использовать?
Если поведение метода не меняется в зависимости от параметров.
Для упрощения мокирования статичных данных.


2. thenThrow

thenThrow позволяет настроить метод на выброс исключения при его вызове.

Копировать код
List<String> mockList = Mockito.mock(List.class);

// Настраиваем метод
Mockito.when(mockList.get(1)).thenThrow(new RuntimeException("Error occurred"));

// Попробуем вызвать
try {
mockList.get(1); // Бросит исключение
} catch (RuntimeException e) {
System.out.println(e.getMessage()); // Выведет: Error occurred
}


Множественные исключения:
Как и в случае с thenReturn, вы можете задать несколько последовательных исключений:
Mockito.when(mockList.get(0))
.thenThrow(new IllegalArgumentException("First error"))
.thenThrow(new RuntimeException("Second error"));

try {
mockList.get(0); // Бросит IllegalArgumentException
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); // Выведет: First error
}

try {
mockList.get(0); // Бросит RuntimeException
} catch (RuntimeException e) {
System.out.println(e.getMessage()); // Выведет: Second error
}


Когда использовать?
Для тестирования обработки исключений.
Для проверки, как система справляется с ошибками (например, сбои базы данных, ошибки сети).


3. thenAnswer

thenAnswer даёт полный контроль над тем, как метод мока реагирует на вызовы. Вы можете задать сложную логику, которая учитывает переданные параметры или состояние теста.

Пример:
List<String> mockList = Mockito.mock(List.class);

// Настраиваем кастомное поведение
Mockito.when(mockList.get(anyInt())).thenAnswer(invocation -> {
int index = invocation.getArgument(0);
return "Value at index " + index;
});

// Проверяем
System.out.println(mockList.get(0)); // Выведет: Value at index 0
System.out.println(mockList.get(5)); // Выведет: Value at index 5


Особенности:
Полезен для создания динамического поведения.
Работает через интерфейс Answer, который предоставляет доступ к объекту вызова (InvocationOnMock).
Может быть использован для логирования или трассировки вызовов.


Реализация сложной логики
Допустим, вы хотите, чтобы метод мока возвращал разные значения в зависимости от индекса:
Mockito.when(mockList.get(anyInt())).thenAnswer(invocation -> {
int index = invocation.getArgument(0);
if (index % 2 == 0) {
return "Even Index";
} else {
return "Odd Index";
}
});

System.out.println(mockList.get(2)); // Выведет: Even Index
System.out.println(mockList.get(3)); // Выведет: Odd Index


#Java #Training #Spring #Testing #Mockito #thenReturn #thenThrow #thenAnswer
Логирование вызовов:
Mockito.when(mockList.get(anyInt())).thenAnswer(invocation -> {
int index = invocation.getArgument(0);
System.out.println("Method called with index: " + index);
return "Logged Value";
});

System.out.println(mockList.get(10)); // Лог: Method called with index: 10
// Вывод: Logged Value


Полный пример с использованием всех трёх методов

Представим сервис для обработки заказов:
@Service
public class OrderService {
public String createOrder(String productId) {
return "Order created for product: " + productId;
}

public void cancelOrder(String orderId) {
throw new UnsupportedOperationException("Cancel not supported");
}

public String getOrderStatus(String orderId) {
return "Status for order " + orderId;
}
}


Тест:
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {

@Mock
private OrderService orderService;

@Test
void testThenReturn() {
// Настраиваем thenReturn
Mockito.when(orderService.createOrder("123")).thenReturn("Mocked Order Created");

String result = orderService.createOrder("123");
Assertions.assertEquals("Mocked Order Created", result);
}

@Test
void testThenThrow() {
// Настраиваем thenThrow
Mockito.when(orderService.cancelOrder("invalid")).thenThrow(new IllegalArgumentException("Invalid Order"));

Assertions.assertThrows(IllegalArgumentException.class, () -> {
orderService.cancelOrder("invalid");
});
}

@Test
void testThenAnswer() {
// Настраиваем thenAnswer
Mockito.when(orderService.getOrderStatus(anyString())).thenAnswer(invocation -> {
String orderId = invocation.getArgument(0);
return "Dynamic status for " + orderId;
});

String status = orderService.getOrderStatus("456");
Assertions.assertEquals("Dynamic status for 456", status);
}
}


#Java #Training #Spring #Testing #Mockito #thenReturn #thenThrow #thenAnswer