Dependency Injection si Testing in JUnit 5

Abstract: In cadrul acestei serii vom aborda oportunitatile pe care le avem ca sa oferim parametri pentru JUnit 5 unit tests, prin dependency injection. Vom arata cum putem face asta cat mai eficient, cum sa folosim parameter resolvers diferiti dar si cum sa scriem teste repeated si parameterized.

Apr 6, 2020 80
Abstract: In cadrul acestei serii vom aborda oportunitatile pe care le avem ca sa oferim parametri pentru JUnit 5 unit tests, prin dependency injection. Vom arata cum putem face asta cat mai eficient, cum sa folosim parameter resolvers diferiti dar si cum sa scriem teste repeated si parameterized.

1. Dependency injection in JUnit 5


In toate versiunile anterioare ale JUnit, la test constructors sau metode nu aveam parametri. Una dintre schimbarile majore in JUnit 5 este ca test constructors si metodelor le este permis sa aiba parametri. Acest lucru vine la pachet cu un grad mai mare de flexibilitate si permite dependency injection pentru constructori si metode.

ParameterResolver defineste API-ul pentru test extensions care vor sa resolve in mod dinamic parametrii la runtime. Daca un test class constructor, test method sau lifecycle method accepta un parametru, parametrul trebuie sa fie rezolvat la runtime de un ParameterResolver inregistrat. Putem injecta cati parametri vrem, in ce ordine vrem.

Desi exista in acest moment trei built-in resolvers, alti parameter resolvers trebuie sa fie permisi in mod explicit prin inregistrarea extensiilor potrivite cu @ExtendWith. Parameter resolvers inregistrati in mod automat sunt:

  • TestInfoParameterResolver: daca un constructor sau un method parameter este de tipul TestInfo, TestInfoParameterResolver furnizeaza o instanta a TestInfo care corespunde cu containerul sau testul actual ca valoare pentru parametru. TestInfo este o clasa a carei obiecte sunt folosite sa injecteze informatii despre testul sau containerul executat in acel moment in metodele @Test, @BeforeEach, @AfterEach, @BeforeAll, si @AfterAll. TestInfo poate sa fie folosit pentru a obtine informatii despre containerul sau testul actual, cum ar fi display name, test class, test method sau associated tags. Display name este fie un nume tehnic, precum numele test class sau test method, sau un nume personalizat configurat via @DisplayName. Listing 1 arata cum sa folosim un parametru TestInfo ca argument al unui constructor sau al unei metode adnotate.

The usage of TestInfo parameters.JPG


In exemplu anterior, injectam un parametru TestInfo in constructor si in 3 metode. Constructorul verifica faptul ca display name este exact TestInfoTest, propriul nume (1). Acesta este comportamentul default pe care il poti varia cu ajutorul adnotarilor @DisplayName, dupa cum veti vedea.

Apoi, metoda adnotata @BeforeEach este executata inainte de fiecare test. Are un parametru TestInfo injectat si verifica faptul ca displayed name este cel asteptat, insemnand fie numele metodei, fie cel specificat de adnotarea @DisplayName (2).

Ambele teste au un parametru TestInfo injectat. Fiecare din ele verifica faptul ca display name este cel asteptat, adica fie numele metodei pentru primul test (3) sau cel specificat de adnotarea @DisplayName pentru testul doi (4).

Amintim faptul ca built-in TestInfoParameterResolver ofera o instanta a TestInfo care corespunde containerului actual sau test ca valoare pentru parametri asteptati din partea constructorului si a metodelor.

  • TestReporterParameterResolver: daca un constructor sau method parameter este de tipul TestReporter, TestReporterParameterResolver ofera o instanta a TestReporter. TestReporter este o interfata functionala si astfel poate sa fie folosita ca assigment target pentru o expresie lambda sau method reference. Parametrii de tipul TestReporter pot sa fie injectati in metode test classes adnotate cu @BeforeEach, @AfterEach si @Test. TestReporter poate sa fie folosit pentru a publica date aditionale despre current test run. Listing 2 arata cum sa folosim un parametru TestReporter ca argument al metodelor adnotate @Test.

The usage of TestReporter parameters.JPG


In exemplul anterior, un parametru TestReporter este injectat in trei metode.

In prima metoda este folosit pentru a publica o single value entry (1).

In a doua metoda este folosit pentru a publica o key-value pair (2).

In cea de-a treia metoda, mai intai construim o harta (3), apoi o populam cu doua key-values pairs (4), apoi o folosim pentru a publica harta construita (5).

Amintim faptul ca built-in TestReporterParameterResolver ofera instanta TestReporter necesara pentru a publica intrarile.

Rezultatul testului apare mai jos.

Test execution.png


  • RepetitionInfoParameterResolver: daca un method parameter dintr-o metoda @RepeatedTest, @BeforeEach, sau @AfterEach este de tipul RepetitionInfo, RepetitionInfoParameterResolver ofera o instanta a RepetitionInfo. RepetitionInfo poate sa fie folosita pentru a obtine informatii legate de repetitia curenta si numarul total de repetitii pentru @RepeatedTest corespondent. RepetitionInfoParameterResolver nu este inregistrat in afara contextului unui @RepeatedTest. Vom discuta mai multe despre teste repetate si vom oferi si exemple in urmatorul articol.

Vrei sa inveti mai multe despre aceasta tehnologie? Descopera cursurile noastre.

Catalin Tudose
Java and Web Technologies Expert

Daca iti place acest articol, distribuie-l si prietenilor tai!




Luxoft Warsaw - Warsaw Spire, plac Europejski 1, 00-844 Warszawa
Dimitrie Pompeiu nr 5-7 , building C, Et. 5, sect 2, Bucharest, 014459

Contact phone:

021 371 4858
Luxoft Poland Wroclaw - Silver Tower pl. Konstytucji 3-go Maja 3 50-048 Wroclaw
Aleja Generała Tadeusza Bora-Komorowskiego 25, Quattro Business Park Five, 31-476 Kraków, Poland

Contact phone:

+48 122110650
Success
Iti multumim.
Inregistrarea ta a fost trimisa.