Введение Mockito Mocks в бобы весны

Инъекция Mockito Mocks в бобы

1. обзор

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

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

Инъекция макета - это чистый способ ввести такую ​​изоляцию.

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

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


    org.springframework.boot
    spring-boot-starter
    1.3.1.RELEASE


    org.springframework.boot
    spring-boot-starter-test
    1.3.1.RELEASE
    test


    org.mockito
    mockito-core
    2.21.0

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

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

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

Сначала мы напишем бизнес-логику, которая будет проверена:

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

КлассNameService будет внедрен в:

@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 для сканирования компонентов и инициализации приложения:

@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 and @ActiveProfiles и добавьте аннотацию@ContextConfiguration(classes = NameServiceTestConfiguration.class) к классуUserServiceTest.

4. Заключение

В учебном пособии показано, как вводить макеты Mockito в Spring Beans. Реализацию можно найти вexample GitHub project.