Перейти к основному содержимому

Внедрение Mockito Mocks в Spring Beans

· 3 мин. чтения

1. Обзор

В этом руководстве мы обсудим, как использовать внедрение зависимостей для вставки макетов Mockito в Spring Beans для модульного тестирования.

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

Внедрение макета — это чистый способ ввести такую изоляцию.

2. Зависимости Maven

Нам нужны следующие зависимости Maven для модульных тестов и фиктивных объектов:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
</dependency>

Мы решили использовать Spring Boot для этого примера, но классический Spring тоже подойдет.

3. Написание теста

3.1. Бизнес-логика

Во-первых, давайте создадим простой сервис, который мы будем тестировать:

@Service
public class NameService {
public String getUserName(String id) {
return "Real user name";
}
}

Затем мы внедрим его в класс UserService :

@Service
public class UserService {

private NameService nameService;

@Autowired
public UserService(NameService nameService) {
this.nameService = nameService;
}

public String getUserName(String id) {
return nameService.getUserName(id);
}
}

В этой статье указанные классы возвращают одно имя независимо от предоставленного идентификатора. Это сделано для того, чтобы мы не отвлекались на тестирование какой-либо сложной логики.

Нам также понадобится стандартный основной класс Spring Boot для сканирования bean-компонентов и инициализации приложения:

@SpringBootApplication
public class MocksApplication {
public static void main(String[] args) {
SpringApplication.run(MocksApplication.class, args);
}
}

3.2. Тесты

Теперь перейдем к тестовой логике. Прежде всего, мы должны настроить контекст приложения для тестов:

@Profile("test")
@Configuration
public class NameServiceTestConfiguration {
@Bean
@Primary
public NameService nameService() {
return Mockito.mock(NameService.class);
}
}

Аннотация @Profile указывает Spring применять эту конфигурацию только тогда, когда активен «тестовый» профиль. Аннотация @Primary предназначена для того, чтобы убедиться, что этот экземпляр используется вместо реального для автоматического подключения. Сам метод создает и возвращает макет Mockito нашего класса NameService .

Теперь мы можем написать модульный тест:

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MocksApplication.class)
public class UserServiceUnitTest {

@Autowired
private UserService userService;

@Autowired
private NameService nameService;

@Test
public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name");
String testName = userService.getUserName("SomeId");
Assert.assertEquals("Mock user name", testName);
}
}

Мы используем аннотацию @ActiveProfiles , чтобы включить «тестовый» профиль и активировать фиктивную конфигурацию, которую мы написали ранее. В результате Spring автоматически подключает реальный экземпляр класса UserService , но макет класса NameService . Сам тест является довольно типичным тестом JUnit+Mockito. Мы настраиваем желаемое поведение макета, затем вызываем метод, который хотим протестировать, и утверждаем, что он возвращает ожидаемое значение.

Также возможно (хотя и не рекомендуется) избегать использования профилей среды в таких тестах. Для этого мы удаляем аннотации @Profile и @ActiveProfiles и добавляем аннотацию @ContextConfiguration(classes = NameServiceTestConfiguration.class) в класс UserServiceTest .

4. Вывод

В этой краткой статье мы узнали, как легко внедрить моки Mockito в Spring Beans.

Как обычно, все образцы кода доступны на GitHub .