spock mocking stubbing
Posmehovanje, štancanje in vohunjenje s Spockom:
Parametrizirano testiranje v Spock Framework je bilo v tem podrobno razloženo Serija vadnic o Spocku .
Posmeh in trn sta eden najpomembnejših gradnikov obsežnih enotnih testov. Podpora za posmeh in subbing je kot češnja na torti za ogrodje.
Za obstoječe ogrodje, kot so JUnit, JBehave itd., Podpora za posmeh in škrbine ni nujna, zato mora razvijalec uporabiti knjižnice drugih proizvajalcev, kot so Mockito, PowerMock, EasyMock itd., Da jih lahko uporabi v enotni testi.
Da bi razumeli posmehe in primere njihove uporabe, si lahko ogledate našo serijo Vadnica za Mockito .
V tej vadnici bomo izvedeli več o vgrajenih funkcijah posmehovanja in preprečevanja, integriranih v samo knjižnico Spock, kar bi omogočilo uporabo lažje sintakse Groovy in s tem zmanjšalo potrebo po dodajanju / vključevanju drugih 3rdpartijske knjižnice.
V svoje teste lahko vedno vključite druge posmehljive okvire, saj je vsa veljavna koda Java veljavna tudi koda Groovy.
Kaj se boste naučili:
- Prijava v preskusu
- Posmehovanje Spocku
- Zatiranje v Spocku
- Vohunjenje v Spocku
- Zaključek
- Izvorna koda za aplikacijo
- Priporočeno branje
Prijava v preskusu
Najprej določimo vzorec Java-aplikacije, ki jo bomo preizkusili z uporabo lažnih in šibkih spokov v okviru Spock.
Delali bomo na aplikaciji StudentGradeCalculator, ki vzame skupni rezultat iz abstraktne baze podatkov za dani ID študenta in ima preprosto logiko dodeljevanja ocen, odvisno od vrednosti skupnega rezultata. Uporabili bomo vmesnik zbirke podatkov, ki ima malo metod za pridobivanje in posodabljanje ocen in ocen študentov.
Koda aplikacije bo na voljo v zadnjem razdelku te vadnice.
Posmehovanje Spocku
Video-vadnica
V tem razdelku bomo videli, kako ustvariti in inicializirati Mocks v okviru Spock in kako validirati interakcije v lažni obliki, tj. Validacija klicev v modele se je zgodila v skladu s pričakovanji preskušane metode.
Z Mocksi vam ni treba izvajati veliko nastavitev, lahko pa preverite interakcije, ki so se zgodile z lažnimi predmeti, ki so bili dostavljeni v preizkušeno aplikacijo.
Z posmehom lahko počnete stvari, kot so:
- S kakšnimi argumenti so bili zasmehovani?
- Kakšno je bilo skupno število klicev itd.?
- Ugotovitev vrstnega nasmeha.
Oglejmo si preprost primer StudentGradeCalculator, kjer dobavljamo izsiljeni objekt izvedbe baze podatkov in preverjamo interakcije z Mockom. Poskusili bomo razumeti posmehljive funkcije s preprostimi primeri.
Upoštevajte, da bi se morala vsa preverjanja interakcij izvajati v bloku »takrat« po dogovoru.
Spodaj je koda preskušane metode (ki bo imenovano v kdaj: ”Blok)
public String calculateStudentGrade(String studentId) { String grade; // check if grade is already there in database grade = studentDatabase.getStudentGrade(studentId); if(grade!=null && !grade.isEmpty()) { return grade; } List scoreList = studentDatabase.getStudentScores(studentId); Float totalScore = 0F; if(scoreList !=null) totalScore = scoreList.stream().reduce(0F,(a,b)->a+b); if(totalScore > 90) { grade = 'A'; } else if (totalScore > 80) { grade = 'B'; } else { grade = 'C'; } // update the calculated grade in database studentDatabase.updateStudentGrade(studentId, grade); return grade; }
# 1) Preverjanje interakcij z natančnimi argumenti: Najprej preverimo interakcije s točno pričakovanimi argumenti. Tu bomo pričakovali, da bodo posmehljive metode poklicane z natančnimi argumenti (v skladu s tokom izvajanja metode).
Tukaj študentska baza podatkov 'Je posmeh vmesnika baze podatkov, za katerega preverjamo interakcije.
def 'illustrate mocks for interaction verification with arguments'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade('123','C') 1*studentDatabase.getStudentGrade('123') }
Kot je prikazano zgoraj, potrjujemo z natančnimi argumenti, tako da je bilo treba izsiljeno izvedbo poklicati s. Vse spremembe teh argumentov bodo povzročile, da test ne bo uspel, dnevnik napak pa bo prikazal ustrezen razlog.
kako postati knjiga voditeljev
Poskusimo spremeniti oceno v » updateStudentGrade «Na» A «namesto dejansko imenovanega» C «in poglejte, kakšno napako dobimo, ko se test izvede.
Too few invocations for: 1*studentDatabase.updateStudentGrade('123','A') (0 invocations) Unmatched invocations (ordered by similarity): 1 * studentDatabase.updateStudentGrade('123', 'C') 1 * studentDatabase.getStudentScores('123')
Prikazala se bo napaka, kot je »Premalo klicev«, saj s priloženimi argumenti ne najde mock klica.
#two) Zdaj pa poglejmo, kako preveriti Mock interakcije, ne da bi navedli dejanske vrednosti argumentov, tj. Kar nas zanima, je samo vedeti, da je bil lažni priklican v metodi, vendar ne s kakšnimi argumenti.
Tovrstne zahteve so najpogostejše med pisanjem preskusov na enoto za dejansko proizvodno kodo, saj ni vedno enostavno prepoznati dejanskih argumentov, ki so v bistvu odvisni od osnovne poslovne logike preizkušane aplikacije.
Sintaksa je preprosta, za argument, kjer dejanska vrednost ni znana, morate uporabiti podčrtaj '_'.
Na primer, če želite preveriti vrednost String, lahko samo omenite “_ Kot niz 'Namesto argumenta v preskusu in mora prenesti za katero koli vrednost String (podobno za druge primitivne vrste podatkov in vrste podatkov po meri).
Razumimo to s primerom
def 'illustrate mocks for interaction verification with generic matchers'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) 1*studentDatabase.getStudentGrade('123') }
Pomembno je omeniti, da lahko vedno kombinirate in ujemate, kateri argumenti so znani in kateri ne. Na primer, v spodnjem primeru potrjujemo interakcijo enega lažnega z dejanskimi argumenti, drugega pa z ohlapnimi tekmami.
# 3) Na koncu si oglejmo še scenarij, v katerem lahko ugotovimo vrstni red lažnega priklica, tj. Kakšen vrstni red so bili poklicani, ko je bil test izveden.
Včasih je nujno potrditi potek dogodkov, kadar je v preizkušeni aplikaciji vpletenih več sodelavcev / posmehov, koristno pa je razumeti in potrditi, da so bile metode poklicane v vnaprej določenem zaporedju.
def 'illustrate mocks for validating order'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.getStudentGrade('123') then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) }
To lahko dosežemo s preprosto uporabo več blokov »then:« v vrstnem redu pričakovanih Mock zaporedja. Če omenjeno zaporedje ni ustrezalo dejanskemu vrstnemu redu klica, se prikaže napaka s podrobnim opisom »Napačen vrstni red klica«.
Če na primer spremenim zgornji vrstni red potem izjave, bo izvajanje preizkusa povzročilo napako, kot je prikazano spodaj.
Wrong invocation order for: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) (1 invocation) Last invocation: studentDatabase.updateStudentGrade('123', 'C')
Zatiranje v Spocku
Video-vadnica
Raziskovali smo vse o posmehovanju, zdaj pa poglejmo, kako definirati zatiče na posmehanih predmetih. Zatiranje ni nič drugega kot nastavitev vnaprej določenih ali pripravljenih odzivov na Mock klice za preizkušanje različnih tokov / scenarijev preskušane aplikacije.
Zamislite si to kot programiranje lažnega vračanja vnaprej določene vrednosti, ko je bila poklicana. Nadaljevali bomo z isto aplikacijo StudentGradeCalculator in onemogočili klice vmesnika baze podatkov, da bomo preizkusili različne scenarije.
Stub je kot posmeh, ki na nek način posnema vedenje resničnega predmeta. Lahko ga preprosto pokličete kot programirani Mock.
Stubbing Sintaksa
Sintaksa za stubbing je 2 operaterja desnega premika - tj. >> '
Če želite nastaviti klic na kateri koli klic, ga lahko določite na naslednji način:
StubbedObject.StubbedMethod(//argumentList) >> “Stubbed Response”
Zdaj razumemo različne scenarije trma s primeri.
# 1) Stub z dejanskimi parametri: Če so argumenti znani vnaprej ali če želite nastaviti stub samo, kadar je klic z navedenimi argumenti, lahko uporabite ta način določanja stub-ov.
def 'illustrate stubs with exact matchers'() { given: studentDatabase.getStudentScores('123') >> [20F, 30F, 50F] when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' }
Tu lahko vidite, da je škrbina nastavljena z natančnim argumentom, tj. StudentId v tem primeru kot '123' (za katero koli drugo vrednost škrbine ne bo poklicana in vrnjen bo privzeti odgovor).
# 2) Zatiranje z blagimi tekmovalci: Če argumenti niso znani (ali niso pomembni), jih lahko ohlapno omenimo, kot smo to storili za posmehe in sintaksa ostaja enaka, tj. Podčrtaj '_'.
def 'illustrate stubs with loose matchers'() { given: studentDatabase.getStudentScores(_ as String) >> [20F, 30F, 10F] when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' }
# 3) Poglejmo še en hiter primer, ko smo nastavili škrbino, da vržemo izjemo.
Ti scenariji so zelo koristni za preverjanje logike ravnanja z napakami v preskušani aplikaciji (kot v resničnem svetu generiranje vseh izjem dejansko ni mogoče, vendar bi lahko nastavili preprosto ohišje, ki vrne katero koli izjemo, ki jo želimo, in jo nato uveljavi v takratni blok).
def 'illustrate stubs with exceptions thrown'() { given: studentDatabase.getStudentScores(_ as String) >> {throw new RuntimeException()} when: studentReportGenerator.calculateStudentGrade('123') then: thrown(RuntimeException.class) }
Vohunjenje v Spocku
Vohuni temeljijo na resničnih predmetih torej potrebujejo izvedbo vmesnika in ne abstraktnega vmesnika samega. Vohuni so zmogljivi in vam lahko omogočijo, da za testno aplikacijo pokličete prave metode in preverite, za katere argumente so bile metode pozvane.
Vohuni omogočajo tudi določanje delnih posmehov na primerke vohunjenih predmetov. predpostavimo, da želite določiti obnašanje nekaterih metod na objektu, potem lahko in dovolite, da se preostali kliče kot pravi klic metode.
Ti so običajno koristni v razmerah, ko morda obstajajo nekatere metode vmesnikov, ki niso implementirane, in je malo drugih, ki so popolnoma funkcionalne. Tako se lahko kot razvijalec odločite, da boste preprečili neizvedene in poklicali resnične izvedbe funkcionalnih metod.
Upoštevati je treba, da bo za predmete Špij, če niso definirani škrbine, privzeto vedenje, da pokliče resnično izvedbo. Povedano je, da vohunov ne bi smeli pogosto klicati, vse scenarije pa je mogoče doseči z uporabo ponaredkov in kombinacij.
Oglejmo si nekaj primerov uporabe Spies v okviru Spock, ki uporablja isti primer StudentGradeCalculator (Ustvarili smo resnično izvedbo Študentska baza podatkov ki je uporaba v pomnilniku z uporabo HashMap za ponazoritev klicanja pravih metod in vračanja podatkov. Koda bo na voljo v zadnjem delu vadnice):
# 1) Vohunjenje s kombinacijo klicev klica in resničnih metod
def 'illustrate spies'() { given: StudentDatabase spiedStudentDatabase = Spy(StudentDatabase.class) def studentReportGenerator = new StudentReportGenerator(spiedStudentDatabase) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' 1*spiedStudentDatabase.getStudentGrade(_ as String) >> 'A' }
Zgornji primer ponazarja sintakso za ustvarjanje vohuna z uporabo okvira Spock. Škrbina je definirana v času same izjave.
Tudi vohunjene klice je mogoče preveriti, kot je prikazano v bloku then (z ohlapnimi ujemanji argumentov, ki jih je mogoče definirati za katere koli posebne argumente).
# 2) Vohunjenje z uporabo vseh resničnih klicev metode
def 'illustrate spies with real method call'() { given: StudentDatabase spiedStudentDatabase = Spy(StudentDatabase.class) def studentReportGenerator = new StudentReportGenerator(spiedStudentDatabase) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' 1*spiedStudentDatabase.getStudentGrade('123') }
V zgornjem primeru, ker nismo omenili nobenega omamljenega vedenja, bodo vsi klici namenjeni resnični izvedbi.
Zaključek
V tej vadnici smo izvedeli vse o vgrajenih tehnikah Mock Stub in Spy z uporabo okvira Spock. Spock to olajša z združevanjem teh funkcij kot dela samega ogrodja z bolj berljivo groovsko sintakso skupaj z manjšo osnovno kodo.
Mocks, Stubs in Spies se pogosto uporabljajo pri testiranju enot za povečanje pokritosti in preizkušanje ali potrjevanje osnovne poslovne logike preskušane aplikacije.
Izvorna koda za aplikacijo
StudentReportGenerator.java - to je metoda / aplikacija, ki se preskuša
package app.studentScores; import java.util.List; public class StudentReportGenerator { public IStudentDatabase studentDatabase; public StudentReportGenerator(IStudentDatabase studentDatabase) { this.studentDatabase = studentDatabase; } public String calculateStudentGrade(String studentId) { String grade; // check if grade is already there in database grade = studentDatabase.getStudentGrade(studentId); if(grade!=null && !grade.isEmpty()) { return grade; } List scoreList = studentDatabase.getStudentScores(studentId); Float totalScore = 0F; if(scoreList !=null) totalScore = scoreList.stream().reduce(0F,(a,b)->a+b); if(totalScore > 90) { grade = 'A'; } else if (totalScore > 80) { grade = 'B'; } else { grade = 'C'; } // update the calculated grade in database studentDatabase.updateStudentGrade(studentId, grade); return grade; } }
IStudentDatabase.java - Vmesnik zbirke podatkov
package app.studentScores; import java.util.List; public interface IStudentDatabase { List getStudentScores(String studentId); void updateStudentGrade(String studentId, String grade); String getStudentGrade(String studentId); }
StudentDatabase.java - InMemory izvedba vmesnika IStudentDatabase.java
package app.studentScores; import java.util.*; public class StudentDatabase implements IStudentDatabase { private Map scoreMap; private Map gradeMap; public StudentDatabase() { this.scoreMap = new HashMap(); this.gradeMap = new HashMap(); scoreMap.put('123', Arrays.asList(40F, 30F, 30F)); scoreMap.put('456', Arrays.asList(10F, 10F, 30F)); gradeMap.put('123', 'C'); gradeMap.put('456', 'A'); } @Override public List getStudentScores(String studentId) { return scoreMap.get(studentId); } @Override public void updateStudentGrade(String studentId, String grade) { gradeMap.put(studentId,grade); } @Override public String getStudentGrade(String studentId) { return gradeMap.get(studentId); } }
V naši prihajajoči vadnici bomo videli, kako integrirati Spockov okvir z drugimi okviri in tehnologijami za testiranje.
PREV Vadnica | NASLEDNJA Vadnica
Priporočeno branje
- Pisanje enotnih testov s Spock Framework
- Vprašanja za intervju z Spockom z odgovori (najbolj priljubljeno)
- Spock za integracijo in funkcionalno testiranje s selenom
- Podatkovno ali parametrizirano testiranje s Spock Framework
- Vadnica za Spock: Testiranje s Spockom in Groovyjem
- Najboljša BREZPLAČNA vadnica za C #: Ultimate C # Guide za začetnike
- Testiranje obremenitve z vadnicami HP LoadRunner
- Datum in čas v C ++ z primeri