spock mocking stubbing
Mocking, Stubbing and Spying with Spock:
Parametrizované testování v Spock Framework bylo v tomto podrobně vysvětleno Série výcvikových kurzů na Spocku .
Mocking a Stubbing jsou jedním z nejdůležitějších stavebních kamenů rozsáhlých testů jednotek. Podpora posměchu a subbing je jako třešnička na dortu pro rámec.
U stávajících rámců jako JUnit, JBehave atd. Podpora pro falešné a pahýly nevychází z krabice, proto vyžaduje, aby vývojář použil knihovny třetích stran, jako jsou Mockito, PowerMock, EasyMock atd., Aby je mohl použít v jednotkové testy.
Abychom porozuměli falešným zprávám a útržkům a jejich případům použití, můžete se podívat na naši sérii Výukový program pro Mockito .
V tomto tutoriálu se dozvíme více o vestavěných funkcích Mocking a Stubbing integrovaných do samotné knihovny Spock, což by zase umožnilo používat snadnější syntaxi Groovy a tím snižuje potřebu přidat / zahrnout další 3rdstranické knihovny.
Do testů můžete vždy zahrnout další rámcová nastavení, protože veškerý platný kód Java je platný také kód Groovy.
Co se naučíte:
- Testovaná aplikace
- Mocking in Spock
- Zastrčení Spocka
- Špionáž ve Spocku
- Závěr
- Zdrojový kód aplikace
- Doporučené čtení
Testovaná aplikace
Pojďme si nejprve definovat ukázkovou Java aplikaci, kterou budeme testovat pomocí falešných zpráv a pahýlů v rámci Spocku.
Budeme pracovat na aplikaci StudentGradeCalculator, která vezme celkové skóre z abstrahované databáze pro dané ID studenta a má jednoduchou logiku přiřazování známek v závislosti na hodnotě celkového skóre. Použijeme databázové rozhraní, které má několik metod k načtení a aktualizaci skóre a známek studentů.
Kód aplikace bude k dispozici v poslední části tohoto kurzu.
Mocking in Spock
Výukový program
V této části uvidíme, jak vytvořit instanci a inicializovat Mocks v rámci Spocku a jak ověřit interakce na falešném, tj. Ověření hovorů na falešné zprávy proběhlo podle očekávání testované metody.
S Mocks nemusíte dělat mnoho nastavení, ale můžete ověřit interakce, které se staly s falešnými objekty dodávanými do testované aplikace.
S výsměchem můžete dělat například:
- S jakými argumenty byli vysmíváni?
- Jaký byl celkový počet vyvolání atd.?
- Zjištění pořadí falešných zpráv.
Podívejme se na jednoduchý příklad StudentGradeCalculatoru, kde dodáváme zesměšňovaný objekt implementace databáze a ověřujeme interakce s Mock. Pokusíme se pochopit posměšné funkce na jednoduchých příkladech.
Všimněte si, že všechna ověření interakce by se měla konat v bloku „then“ podle konvence.
Níže je uveden kód testované metody (který bude volán v „ když: ”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) Ověření interakcí přesnými argumenty: Pojďme nejprve ověřit interakce s přesně očekávanými argumenty. Zde budeme očekávat, že posměšné metody budou volány s přesnými argumenty (podle toku provádění metody).
Tady ' studentDatabase „Je Mock databázového rozhraní, pro které ověřujeme interakce.
def 'illustrate mocks for interaction verification with arguments'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade('123','C') 1*studentDatabase.getStudentGrade('123') }
Jak je znázorněno výše, ověřujeme pomocí přesných argumentů, takže k posměšné implementaci muselo být voláno. Jakékoli změny těchto argumentů způsobí selhání testu a protokol chyb ukazuje příslušný důvod.
Zkusme změnit známku v „ updateStudentGrade ”Až“ A ”namísto skutečně nazývaného“ C ”a uvidíte, jakou chybu dostaneme při provedení testu.
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')
Ukáže chybu jako „Příliš málo vyvolání“, protože nemůže najít Mock vyvolání s dodanými argumenty.
#dva) Nyní se podívejme, jak ověřit interakce Mock bez zadání skutečných hodnot argumentů, tj. To, co nás zajímá, je jen vědět, že falešná metoda byla vyvolána v metodě, ale ne s jakými argumenty.
Tyto typy požadavků jsou nejběžnější při psaní testů jednotek pro skutečný produkční kód, protože není vždy snadné identifikovat skutečné argumenty, které v zásadě závisí na základní obchodní logice testované aplikace.
Syntaxe je jednoduchá, stačí použít podtržítko „_“ pro argument, kde skutečná hodnota není známa.
Například, Chcete-li zkontrolovat jakoukoli hodnotu řetězce, stačí zmínit '_ Jako řetězec.' „Místo argumentu v testu a měl by vyhovovat pro jakoukoli hodnotu řetězce (podobně pro jiné primitivní i vlastní datové typy).
Rozumíme tomu na příkladu
bezplatný zálohovací software pro Windows 8.1
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') }
Důležité je zde poznamenat, že vždy můžete kombinovat, jaké argumenty jsou známé a co není známo. Například v níže uvedeném příkladu ověřujeme interakci jednoho falešného se skutečnými argumenty a druhého s volnými shody.
# 3) Nakonec se podívejme na scénář, kde můžeme zjistit pořadí falešného vyvolání, tj. Jaké pořadí se falešné volaly při provádění testu.
Někdy je zásadní ověřit tok událostí, když je v testované aplikaci více spolupracovníků / falešných účastníků a je užitečné pochopit a ověřit, že metody byly volány v předem určeném pořadí.
def 'illustrate mocks for validating order'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.getStudentGrade('123') then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) }
Toho lze dosáhnout jednoduchým použitím více bloků „then:“ v pořadí očekávání Mock sekvence. Pokud uvedená posloupnost nesplnila skutečné pořadí vyvolání, je vyvolána chyba s podrobným popisem „Chybná objednávka vyvolání“.
Například pokud změním pořadí výše pak příkazy, provedení testu vyvolá chybu, jak je uvedeno níže.
Wrong invocation order for: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) (1 invocation) Last invocation: studentDatabase.updateStudentGrade('123', 'C')
Zastrčení Spocka
Výukový program
vr, který funguje s Xbox One
Prozkoumali jsme vše o posměchu, pojďme se podívat, jak definovat pahýly na zesměšňovaných objektech. Stubbing není nic jiného než nastavení předdefinovaných nebo konzervovaných odpovědí na Mock vyvolání k testování různých toků / scénářů testované aplikace.
Přemýšlejte o tom, že naprogramujete falešnou funkci, která vám při volání vrátí předem definovanou hodnotu. Budeme pokračovat se stejnou aplikací StudentGradeCalculator a stub volání rozhraní databáze k testování různých scénářů.
Stub je jako Mock, který svým způsobem napodobuje chování skutečného objektu. Můžete jej jednoduše nazvat naprogramovaným Mock.
Stubbing Syntax
Syntaxe pro stubbing je 2 operátory posunu doprava - tj. „ >> '
Chcete-li nastavit pahýl u libovolného hovoru, můžete jej definovat takto:
StubbedObject.StubbedMethod(//argumentList) >> “Stubbed Response”
Pojďme nyní pochopit různé scénáře útržků pomocí příkladů.
# 1) Stubbing se skutečnými parametry: Pokud jsou argumenty známy předem nebo pokud chcete nastavit pahýl, pouze když je vyvolání se zadanými argumenty, lze použít tento způsob určení pahýlů.
def 'illustrate stubs with exact matchers'() { given: studentDatabase.getStudentScores('123') >> [20F, 30F, 50F] when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' }
Zde vidíte, že stub byl nastaven s přesným argumentem, tj. StudentId v tomto případě jako „123“ (pro jakoukoli jinou hodnotu nebude stub vyvolán a bude vrácena výchozí odpověď).
# 2) Píchání s shovívavými shovívavci: Pokud argumenty nejsou známy (nebo nejsou důležité), můžeme je zmínit volně, jako jsme to udělali pro falešné zprávy, a syntaxe zůstává stejná, tj. Podtržítko „_“.
def 'illustrate stubs with loose matchers'() { given: studentDatabase.getStudentScores(_ as String) >> [20F, 30F, 10F] when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' }
# 3) Podívejme se na další rychlý příklad, kdy jsme nastavili stub, abychom udělali výjimku.
Tyto scénáře jsou velmi užitečné k ověření logiky zpracování chyb testované aplikace (jako ve skutečném světě generování všech výjimek ve skutečnosti není možné, ale lze nastavit jednoduchý pahýl, který vrátí jakoukoli výjimku, kterou chceme, a poté ji potvrdit v tehdejší blok).
def 'illustrate stubs with exceptions thrown'() { given: studentDatabase.getStudentScores(_ as String) >> {throw new RuntimeException()} when: studentReportGenerator.calculateStudentGrade('123') then: thrown(RuntimeException.class) }
Špionáž ve Spocku
Špioni jsou založeni na skutečných objektech tj. potřebují implementaci rozhraní, nikoli samotné abstraktní rozhraní. Spies jsou mocní a mohou vám umožnit získat skutečné metody volané pro testovanou aplikaci a ověřit, jaké argumenty byly metody požadovány.
Spies také umožňují definovat částečné posměšky na instance sledovaného objektu. tj. předpokládejme, že chcete definovat chování některých metod na objektu, pak můžete a dovolte, aby zbytek byl volán jako skutečné volání metody.
Ty jsou obvykle užitečné v situaci, kdy mohou existovat některé metody rozhraní, které nejsou implementovány, a existuje několik dalších, které jsou plně funkční. Vy jako vývojář se tedy můžete rozhodnout, že budete implementovat ty neimplementované a zavoláte skutečné implementace funkčních metod.
Je třeba poznamenat, že pro Spied objekty, pokud nejsou definovány pahýly, bude výchozím chováním volání skutečné implementace. Z tohoto důvodu by špióni neměli být často voláni a pokrytí všech scénářů lze dosáhnout pomocí falešných zpráv a útržků a jejich kombinací.
Podívejme se na několik příkladů použití Spies v rámci Spock pomocí stejného příkladu StudentGradeCalculator (Vytvořili jsme skutečnou implementaci StudentDatabase což je implementace v paměti pomocí HashMap pro ilustraci volání skutečných metod a vrácení dat. Kód bude k dispozici v poslední části tutoriálu):
# 1) Špionáž pomocí kombinace pahýlů a skutečných volání 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' }
Výše uvedený příklad ilustruje syntaxi pro vytváření Spy pomocí rámce Spock. Útržek je definován v samotném čase deklarace.
Také lze špehovaná volání ověřit, jak je znázorněno v tehdejším bloku (pomocí volných porovnávačů argumentů, které lze definovat pro jakékoli konkrétní argumenty).
# 2) Špionáž pomocí všech skutečných volání metod
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') }
Ve výše uvedeném příkladu, protože jsme nezmiňovali žádné stubbed chování, všechna volání přejdou ke skutečné implementaci.
Závěr
V tomto kurzu jsme se naučili vše o vestavěných technikách pro Mock Stub a Spy pomocí Spock framework. Spock to usnadňuje kombinací těchto funkcí jako součásti samotného rámce s čitelnější groovy syntaxí spolu s kódem malého standardu.
Mocks, Stubs a Spies se značně používají v testování jednotek pro zvýšení pokrytí a testování nebo ověření základní obchodní logiky testované aplikace.
Zdrojový kód aplikace
StudentReportGenerator.java - toto je testovaná metoda / aplikace
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 - rozhraní databáze
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 - implementace rozhraní IStudentDatabase.java InMemory
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šem nadcházejícím tutoriálu uvidíme, jak integrovat rámec Spock s dalšími testovacími rámci a technologiemi.
Výukový program PREV | DALŠÍ výuka
Doporučené čtení
- Psaní testů jednotek pomocí Spock Framework
- Spock Interview Otázky s odpověďmi (nejoblíbenější)
- Spock pro integraci a funkční testování se selenem
- Testování na základě dat nebo parametrizace pomocí Spock Framework
- Výukový program Spock: Testování pomocí Spocka a Groovyho
- Nejlepší ZDARMA C # výukové série: Ultimate C # průvodce pro začátečníky
- Testování zátěže s výukovými programy HP LoadRunner
- Funkce data a času v C ++ s příklady