Инжектиране на Mockito Mocks в пролетни зърна

1. Общ преглед

В тази статия ще покажем как да използваме инжекция на зависимости, за да вмъкнем Mockito макети в Spring Beans за модулно тестване.

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

Инжектирането на макет е чист начин да се въведе такава изолация.

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

Нуждаем се от следните зависимости на Maven за модулните тестове и макетните обекти:

 org.springframework.boot spring-boot-starter 2.2.2.RELEASE   org.springframework.boot spring-boot-starter-test 2.2.2.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"; } }

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

@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 анотацията казва Пролет да прилага тази конфигурация, само когато "тест" профил е активен. В @Primary анотацията е там, за да се уверете, че този случай се използва вместо истински за autowiring. Самият метод създава и връща 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 (класове = NameServiceTestConfiguration.class) към класа UserServiceTest .

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

В този бърз урок показахме колко лесно е да инжектирате Mockito макети в Spring Beans.

Както обикновено, всички примерни кодове са достъпни в GitHub.