← Назад к вопросам

Какую библиотеку использовал при работе с @Mock?

1.2 Junior🔥 151 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Аннотация @Mock и библиотека Mockito

@Mock — это аннотация из библиотеки Mockito, которая является стандартом де-факто для создания моков в Java тестировании. Это один из самых важных инструментов для unit testing.

Что такое Mockito?

Mockito — это фреймворк для создания моков (mock objects) в Unit тестах. Мок — это поддельный объект, который имитирует поведение реального объекта.

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.2.0</version>
    <scope>test</scope>
</dependency>

@Mock аннотация

@Mock создаёт мок-объект для класса. Это удобнее, чем Mockito.mock():

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }
    
    @Test
    void testFindUserById() {
        User mockUser = new User("user1", "alice@example.com");
        when(userRepository.findById("user1"))
            .thenReturn(Optional.of(mockUser));
        
        User result = userRepository.findById("user1").get();
        
        assertEquals("alice@example.com", result.getEmail());
        verify(userRepository).findById("user1");
    }
}

@ExtendWith MockitoExtension (рекомендуется)

@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
    @Mock
    private PaymentService paymentService;
    
    @InjectMocks
    private OrderService orderService;
    
    @Test
    void testCreateOrder_Success() {
        User mockUser = new User("user1", "alice@example.com");
        Payment mockPayment = new Payment("pay123", 99.99);
        
        when(paymentService.processPayment(anyDouble()))
            .thenReturn(mockPayment);
        
        Order result = orderService.createOrder("user1", 99.99);
        
        assertNotNull(result);
        assertEquals("pay123", result.getPaymentId());
        verify(paymentService, times(1)).processPayment(99.99);
    }
}

@InjectMocks аннотация

@InjectMocks автоматически инъектирует @Mock в тестируемый класс через конструктор или setter.

Основные методы Mockito

when().thenReturn() — определить поведение

when(userRepository.findById("user1")).thenReturn(Optional.of(user));
when(userRepository.findById(anyString())).thenReturn(Optional.empty());

thenThrow() — выбросить исключение

when(userRepository.findById("invalid"))
    .thenThrow(new DatabaseException("Connection failed"));

thenAnswer() — сложная логика

when(userRepository.findById(anyString()))
    .thenAnswer(invocation -> {
        String id = invocation.getArgument(0);
        if (id.startsWith("test")) {
            return Optional.empty();
        }
        return Optional.of(new User(id, "email"));
    });

verify() — проверить вызовы

verify(userRepository, times(1)).findById("user1");
verify(userRepository).findById("user1");
verify(userRepository, never()).deleteById("user1");
verify(userRepository, atLeast(2)).findAll();
verifyNoMoreInteractions(userRepository);

anyString(), anyInt(), any() — matchers

when(userRepository.findById(anyString())).thenReturn(Optional.of(user));
when(userRepository.findById(argThat(id -> id.startsWith("admin"))))
    .thenReturn(Optional.of(adminUser));

Spring Test Integration

Если используешь Spring, есть удобная аннотация @MockBean:

@SpringBootTest
public class UserControllerTest {
    
    @MockBean
    private UserService userService;
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Test
    void testGetUser() {
        User mockUser = new User("user1", "alice@example.com");
        when(userService.findById("user1")).thenReturn(Optional.of(mockUser));
        
        ResponseEntity<User> response = restTemplate.getForEntity(
            "/api/v1/users/user1", User.class
        );
        
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertEquals("alice@example.com", response.getBody().getEmail());
    }
}

@Mock vs @Spy

@Mock — полный мок (всё поддельное)

@Mock
private UserRepository userRepository;

userRepository.findAll();

@Spy — частичный мок (реальная логика + override)

@Spy
private UserRepository userRepository = new UserRepositoryImpl();

when(userRepository.findById("user1")).thenReturn(Optional.of(user));
userRepository.findAll();

ArgumentCaptor для проверки параметров

@Test
void testPaymentAudit() {
    when(bankService.transfer(100.0)).thenReturn(true);
    
    paymentService.processPayment(100.0, "user1");
    
    ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
    verify(auditService).log(captor.capture(), anyString());
    
    String logMessage = captor.getValue();
    assertTrue(logMessage.contains("100.0"));
}

Когда использовать @Mock

Используй @Mock когда:

  • Тестируешь зависимость от другого сервиса
  • Не хочешь делать реальный вызов БД
  • Не хочешь делать реальный HTTP запрос
  • Нужно симулировать исключения
  • Нужно проверить, как ваш код вызывает зависимость

Избегай @Mock когда:

  • Тестируешь само поведение репозитория (используй real DB)
  • Можешь обойтись без зависимости
  • Зависимость не имеет сложного поведения

Практические советы

  1. Всегда используй @ExtendWith(MockitoExtension.class)
  2. Предпочитай @InjectMocks для автоинъекции
  3. Используй matchers для гибкости
  4. Проверяй взаимодействие через verify()
  5. Используй ArgumentCaptor для проверки параметров

Заключение

@Mock — это аннотация из Mockito, стандартного фреймворка для мокирования в Java.

Основные понятия:

  • @Mock — создание мок-объекта
  • @InjectMocks — автоинъекция моков
  • when/then — определение поведения
  • verify — проверка взаимодействия
  • @ExtendWith(MockitoExtension.class) — инициализация

Mockito делает Unit тестирование проще и быстрее, позволяя изолировать код от зависимостей.