Injektion af Mockito Mocks i Spring Beans

1. Oversigt

I denne artikel viser vi, hvordan man bruger afhængighedsinjektion til at indsætte Mockito-mocks i Spring Beans til enhedstest.

I virkelige applikationer, hvor komponenter ofte afhænger af adgang til eksterne systemer, er det vigtigt at give korrekt testisolering, så vi kan fokusere på at teste funktionaliteten i en given enhed uden at skulle involvere hele klassehierarkiet for hver test.

Injektion af en mock er en ren måde at indføre en sådan isolation på.

2. Maven-afhængigheder

Vi har brug for følgende Maven-afhængigheder til enhedstestene og de mock-objekter:

 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 

Vi besluttede at bruge Spring Boot til dette eksempel, men klassisk Spring fungerer også fint.

3. Skrivning af testen

3.1. Forretningslogikken

Lad os først oprette en simpel tjeneste, som vi tester:

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

Og indsprøjt det i UserService klasse:

@Service offentlig klasse UserService {privat NameService nameService; @Autowired public UserService (NameService nameService) {this.nameService = nameService; } public String getUserName (String id) {return nameService.getUserName (id); }}

I denne vejledning returnerer de givne klasser et enkelt navn uanset id'et. Dette gøres, så vi ikke bliver distraheret ved at teste nogen kompleks logik.

Vi har også brug for en standard Spring Boot-hovedklasse til at scanne bønnerne og initialisere applikationen:

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

3.2. Testene

Lad os nu gå videre til testlogikken. Først og fremmest skal vi konfigurere applikationskontekst til testene:

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

Det @Profil annotation beder Spring om kun at anvende denne konfiguration, når "test" -profilen er aktiv. Det @Primær kommentar er der for at sikre, at denne forekomst bruges i stedet for en reel til autokabler. Selve metoden skaber og returnerer en Mockito-mock af vores NameService klasse.

Nu kan vi skrive enhedstesten:

@ActiveProfiles ("test") @RunWith (SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration (classes = MocksApplication.class) offentlig klasse UserServiceUnitTest {@Autowired privat UserService userService; @Autowired privat NameService nameService; @Test offentligt ugyldigt nårUserIdIsProvided_thenRetrievedNameIsCorrect () {Mockito.when (nameService.getUserName ("SomeId")). ThenReturn ("Mock user name"); Streng testnavn = userService.getUserName ("SomeId"); Assert.assertEquals ("Mock brugernavn", testnavn); }}

Vi bruger @ActiveProfiles kommentar for at aktivere "test" -profilen og aktivere den mock-konfiguration, vi skrev tidligere. På grund af dette, forårsager Spring automatisk en reel forekomst af UserService klasse, men en hån af NameService klasse. Selve testen er en ret typisk JUnit + Mockito-test. Vi konfigurerer mockens ønskede opførsel og kalder derefter metoden, som vi vil teste, og hævder, at den returnerer den værdi, vi forventer.

Det er også muligt (men ikke anbefalet) at undgå at bruge miljøprofiler i sådanne tests. Fjern det for at gøre det @Profile og @ActiveProfiles kommentarer og tilføj en @ContextConfiguration (klasser = NameServiceTestConfiguration.class) kommentar til UserServiceTest klasse.

4. Konklusion

I denne hurtige vejledning viste vi, hvor let det er at injicere Mockito-mocks i Spring Beans.

Som normalt er alle kodeeksempler tilgængelige på GitHub.