spock mocking stubbing
како да пронађем свој мрежни сигурносни код
Изругивање, стубирање и шпијунирање Споком:
Параметарско тестирање у Споцк Фрамеворк-у је у овоме детаљно објашњено Серија тренинга на Споцк-у .
Изругивање и стубирање су један од најважнијих градивних елемената опсежних Унит тестова. Подршка за ругање и потковање је попут трешње на торти за оквир.
За постојеће оквире као што су ЈУнит, ЈБехаве итд., Подршка за лажне и оштећене датотеке не долази из оквира, стога захтева да програмер користи библиотеке независних произвођача попут Моцкито, ПоверМоцк, ЕасиМоцк итд. Да би их могао користити у јединични тестови.
Да бисте разумели лажне речи и примере њихове употребе, можете погледати нашу серију Моцкито туториал .
У овом упутству ћемо сазнати више о уграђеним функцијама Моцкинг анд Стуббинг интегрисаним у саму Споцк библиотеку, што би заузврат омогућило употребу лакшег Гроови синтаксе и тиме смањило потребу за додавањем / укључивањем било којих других 3рдпартијске библиотеке.
Увек можете у тестове укључити друге оквире за исмевање, јер је сав важећи Јава код такође важећи Гроови код.
Шта ћете научити:
- Пријава под тестом
- Ругање Споку
- Стубинг у Споцк-у
- Шпијунирање у Споцку
- Закључак
- Изворни код за апликацију
- Препоручено читање
Пријава под тестом
Хајде да прво дефинишемо примерак Јава апликације, коју ћемо тестирати користећи лажне и кварове у Споцк оквиру.
Радићемо на апликацији СтудентГрадеЦалцулатор која узима укупни резултат из апстрактне базе података за дати ИД ученика и има једноставну логику додељивања оцена у зависности од вредности укупног резултата. Користићемо интерфејс базе података који има неколико метода за дохватање и ажурирање оцена и оцена ученика.
Код за апликацију биће доступан у последњем одељку овог водича.
Ругање Споку
Видео-водич
У овом одељку ћемо видети како да направимо инстанцу и иницијализујемо Моцкс у Споцк оквиру и како да потврдимо интеракције на лажном моделу, тј. Валидација позива на лажне дешавања догодила се у складу са очекивањима методе која се тестира.
Са Моцкс-ом не морате да радите пуно подешавања, али можете да потврдите интеракције које су се догодиле са лажним објектима испорученим у апликацију која се тестира.
Са подсмехом можете радити следеће ствари:
- Са којим аргументима су се изругивали?
- Колики је био укупан број позива итд.?
- Утврђивање редоследа исмевања.
Погледајмо једноставан пример СтудентГрадеЦалцулатор, где испоручујемо исмевани објекат имплементације базе података и валидирамо интеракције са Моцк-ом. Покушаћемо да разумемо подругљиве функције на једноставним примерима.
Имајте на уму да би се сва валидација интеракције требала одвијати у блоку „тада“ према договору.
Испод је шифра методе која се испитује (који ће бити позван у „ када: ' блокирати)
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) Провера ваљаности интеракција тачним аргументима: Прво потврдимо интеракције тачно очекиваним аргументима. Овде ћемо очекивати да се изругиване методе позивају са тачним аргументима (према току извршавања методе).
Овде “ база података ученика ”Је исмевање интерфејса базе података за који валидирамо интеракције.
def 'illustrate mocks for interaction verification with arguments'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade('123','C') 1*studentDatabase.getStudentGrade('123') }
Као што је горе приказано, ми вршимо валидацију са тачним аргументима, тако да је исмевана имплементација морала бити позвана са. Све промене ових аргумената довешће до тога да тест не успе, а дневник грешака показује одговарајући разлог.
Покушајмо да променимо оцену у „ упдатеСтудентГраде “До„ А “уместо заправо названог„ Ц “и погледајте какве грешке добијамо када се тест изврши.
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')
Приказаће се грешка попут „Премало позива“, јер не може пронаћи Моцк инвоцатион са наведеним аргументима.
гоогле вебмастер тоолс алата за сломљене везе
#два) Сада да видимо како да потврдимо Моцк интеракције без давања стварних вредности аргумената, тј. Оно што нас занима је само сазнање да је моцк позван на методу, али не и са којим аргументима.
Ова врста захтева је најчешћа током писања јединичних тестова за стварни производни код, јер није увек лако идентификовати стварне аргументе који у основи зависе од основне пословне логике апликације која се тестира.
Синтакса је једноставна, само треба да користите доњу црту „_“ за аргумент где стварна вредност није позната.
На пример, да бисте проверили да ли постоји вредност Стринга, можете само да поменете „_ Као низ ”На месту аргумента у тесту и требало би да прође за било коју вредност низа (слично за остале примитивне као и прилагођене типове података).
Да разумемо ово на примеру
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') }
Овде је важно напоменути да увек можете да мешате и подударате оно што је познато, а шта не. На пример, у примеру испод, валидирамо интеракцију једног лажног са стварним аргументима, а другог са лабавим подударањем.
# 3) На крају, погледајмо сценарио у којем можемо утврдити редослед лажног позивања, тј. Који редослед су лажни позиви били извршени.
Понекад је неопходно потврдити ток догађаја када је у тест апликацији укључено више сарадника / лажњака и корисно је разумети и потврдити да су методе позване у унапред утврђеном низу.
def 'illustrate mocks for validating order'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.getStudentGrade('123') then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) }
То се може постићи једноставном употребом више блокова „тхен:“ по редоследу Моцк очекивања секвенце. Ако поменута секвенца није задовољила стварни редослед позивања, бациће се грешка са детаљима „Погрешан налог за позивање“.
На пример, ако променим редослед горе наведеног онда наредби, извршавање теста ће избацити грешку као што је приказано доле.
Wrong invocation order for: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) (1 invocation) Last invocation: studentDatabase.updateStudentGrade('123', 'C')
Стубинг у Споцк-у
Видео-водич
Истражили смо све о Ругању, сада да видимо како да дефинишемо Стубс на исмејаним објектима. Стубинг није ништа друго него постављање унапред дефинисаних или припремљених одговора на Моцк позиве за тестирање различитих токова / сценарија апликације која се тестира.
Схватите то као програмирање лажног враћања унапред дефинисане вредности када је позвана. Наставићемо са истом апликацијом СтудентГрадеЦалцулатор и зауставићемо позиве интерфејса базе података да бисмо тестирали различите сценарије.
Стуб је попут подсмеха који на неки начин опонаша понашање стварног објекта. Можете га једноставно назвати програмираним Моцк-ом.
Стуббинг Синтакса
Синтакса стуббинга је 2 оператора десне смене - тј. >> '
Да бисте поставили квар на било који позив, можете га дефинисати на следећи начин:
StubbedObject.StubbedMethod(//argumentList) >> “Stubbed Response”
Хајде сада да разумемо различите сценарије закрчења са Примерима.
# 1) Стубинг са стварним параметрима: Ако су аргументи познати унапред или ако желите да поставите стуб само када је позивање са наведеним аргументима, овај начин одређивања стуб-а може се користити.
def 'illustrate stubs with exact matchers'() { given: studentDatabase.getStudentScores('123') >> (20F, 30F, 50F) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' }
Овде можете видети да је стуб постављен са тачним аргументом, тј. СтудентИд, у овом случају као „123“ (за било коју другу вредност стуб неће бити позван и вратиће се подразумевани одговор).
# 2) Подметање благим подударањем: Ако аргументи нису познати (или нису важни), онда их можемо слободно споменути као што смо то учинили за подсмехе, а синтакса остаје иста, тј. Доња црта „_“.
def 'illustrate stubs with loose matchers'() { given: studentDatabase.getStudentScores(_ as String) >> (20F, 30F, 10F) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'C' }
# 3) Погледајмо још један брзи пример где смо поставили клизање да бисмо избацили изузетак.
Ови сценарији су врло корисни за валидацију логике руковања грешкама апликације која се тестира (као у стварном свету, генерисање свих изузетака заправо није могуће, али може се поставити једноставан кров који враћа изузетак који желимо, а затим га потврдимо у тадашњи блок).
ако је посета ка веб локацији слаба, који тест приступ ће најбоље функционисати
def 'illustrate stubs with exceptions thrown'() { given: studentDatabase.getStudentScores(_ as String) >> {throw new RuntimeException()} when: studentReportGenerator.calculateStudentGrade('123') then: thrown(RuntimeException.class) }
Шпијунирање у Споцку
Шпијуни су засновани на стварним објектима тј. потребна им је имплементација интерфејса, а не сам апстрактни интерфејс. Шпијуни су моћни и могу вам омогућити да добијете праве методе позване за апликацију која се тестира и да верификујете за које аргументе су методе позване.
Шпијуни такође омогућавају дефинисање делимичних исмевања на примере шпијунираног објекта. тј. претпоставимо да желите да дефинишете понашање неких метода на објекту, онда можете и дозволити да се остали позивају као стварни позиви метода.
Они су обично корисни у ситуацији када можда постоје неке методе интерфејса које нису имплементиране, а мало је оних који су потпуно функционални. Дакле, ви као програмер можете да одлучите да зауставите оне који нису имплементирани и да позовете стварне примене функционалних метода.
Треба имати на уму да ће за шпијуниране објекте, уколико нису дефинисани клинови, подразумевано понашање бити позивање стварне имплементације. Имајући то у виду, шпијуне не би требало често позивати, а све покривености сценарија могу се постићи употребом лажних и шалабашких комбинација.
Погледајмо неколико примера коришћења Шпијуна у Споцк оквиру користећи исти пример СтудентГрадеЦалцулатор (Створили смо стварну примену СтудентДатабасе што је имплементација у меморији помоћу ХасхМап за илустрацију позивања стварних метода и враћања података. Код ће бити доступан у последњем одељку водича):
# 1) Шпијунирање користећи комбинацију клица и стварних позива метода
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' }
Горњи пример илуструје синтаксу за стварање Спи-а помоћу Споцк оквира. Стуб се дефинише у само време декларације.
Такође, шпијунирани позиви могу се верификовати као што је приказано у тадашњем блоку (лабавим подударањем аргумената који се могу дефинисати за било које специфичне аргументе).
# 2) Шпијунирање користећи све позиве стварних метода
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') }
У претходном примеру, пошто нисмо споменули било какво каљаво понашање, сви позиви ће ићи на стварну имплементацију.
Закључак
У овом упутству смо научили све о уграђеним техникама Моцк Стуб и Спи користећи Споцк фрамеворк. Споцк олакшава комбиновањем ових карактеристика као дела самог оквира са читљивијом гроови синтаксом, заједно са мањим кодом шаблона.
Моцкс, Стубс и Спиес се у великој мери користе у јединственом тестирању ради повећања покривености и тестирања или валидације основне пословне логике апликације која се тестира.
Изворни код за апликацију
СтудентРепортГенератор.јава - ово је метода / апликација која се тестира
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; } }
ИСтудентДатабасе.јава - Интерфејс базе података
package app.studentScores; import java.util.List; public interface IStudentDatabase { List getStudentScores(String studentId); void updateStudentGrade(String studentId, String grade); String getStudentGrade(String studentId); }
СтудентДатабасе.јава - ИнМемори имплементација интерфејса ИСтудентДатабасе.јава
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); } }
У нашем предстојећем водичу видећемо како интегрисати Споцк фрамеворк са другим оквирима за тестирање и технологијама.
ПРЕВ Туториал |. | СЛЕДЕЋА Лекција
Препоручено читање
- Писање јединствених тестова са Споцк Фрамеворк-ом
- Споцк интервју питања са одговорима (најпопуларније)
- Споцк за интеграцију и функционална испитивања са селеном
- Тестирање на основу података или параметризовано са Споцк Фрамеворк-ом
- Водич за Споцк: Тестирање са Споцком и Гроовием
- Најбољи БЕСПЛАТНИ водичи за Ц #: Крајњи водич за Ц # за почетнике
- Испитивање оптерећења помоћу ХП ЛоадРуннер водича
- Функције датума и времена у Ц ++ са примерима