spock mocking stubbing
Χλευασμός, Stubbing και Κατασκοπεία με Spock:
Παραμετροποιημένος έλεγχος στο Spock Framework εξηγήθηκε λεπτομερώς σε αυτό Σειρά εκπαιδευτικών σεμιναρίων στο Spock .
Το χλευασμό και το Stubbing είναι ένα από τα πιο βασικά δομικά στοιχεία εκτεταμένων δοκιμών μονάδας. Η υποστήριξη για κοροϊδία και υποβιβασμό είναι σαν το κεράσι στο κέικ για ένα πλαίσιο.
Για υπάρχοντα πλαίσια όπως το JUnit, το JBehave κ.λπ., η υποστήριξη για κωμίδες και stubs δεν βγαίνει από το κουτί, επομένως απαιτεί από έναν προγραμματιστή να χρησιμοποιεί βιβλιοθήκες τρίτων όπως το Mockito, το PowerMock, το EasyMock κ.λπ. για να τα χρησιμοποιήσει στο δοκιμές μονάδας.
Για να κατανοήσετε τις χλευές και τα κούτσουρα και τις περιπτώσεις χρήσης τους, μπορείτε να ρίξετε μια ματιά στη σειρά μας Σεμινάριο Mockito .
Σε αυτό το σεμινάριο, θα μάθουμε περισσότερα σχετικά με τις ενσωματωμένες λειτουργίες Mocking and Stubbing που ενσωματώνονται στην ίδια τη βιβλιοθήκη Spock, οι οποίες με τη σειρά τους θα μπορούσαν να χρησιμοποιήσουν την ευκολότερη σύνταξη Groovy και έτσι να μειώσουν την ανάγκη προσθήκης / συμπερίληψης άλλων 3rdβιβλιοθήκες πάρτι.
Μπορείτε πάντα να συμπεριλάβετε άλλα πλαίσια Mocking στις δοκιμές σας, καθώς και όλοι οι έγκυροι κώδικες Java ισχύουν και για τον κωδικό Groovy.
Τι θα μάθετε:
- Εφαρμογή υπό δοκιμή
- Χλευάσουμε στο Spock
- Stubbing στο Spock
- Κατασκοπεία στο Spock
- συμπέρασμα
- Πηγαίος κώδικας για την εφαρμογή
- Συνιστώμενη ανάγνωση
Εφαρμογή υπό δοκιμή
Ας καθορίσουμε πρώτα ένα δείγμα Εφαρμογής Java, το οποίο θα δοκιμάσουμε χρησιμοποιώντας χλευασμούς και στελέχη στο πλαίσιο Spock.
Θα εργαζόμαστε σε μια εφαρμογή StudentGradeCalculator που λαμβάνει τη συνολική βαθμολογία από μια αφηρημένη βάση δεδομένων για μια δεδομένη ταυτότητα μαθητή και έχει μια απλή λογική ανάθεσης βαθμού ανάλογα με την αξία της συνολικής βαθμολογίας. Θα χρησιμοποιήσουμε μια διεπαφή βάσης δεδομένων που έχει λίγες μεθόδους για τη λήψη και ενημέρωση των βαθμολογιών και των βαθμών των μαθητών.
Ο κωδικός για την εφαρμογή θα είναι διαθέσιμος στην τελευταία ενότητα αυτού του σεμιναρίου.
Χλευάσουμε στο Spock
Εκπαιδευτικό βίντεο
Σε αυτήν την ενότητα, θα δούμε πώς να δημιουργούμε και να αρχικοποιούμε το Mocks στο πλαίσιο Spock και πώς να επικυρώνουμε τις αλληλεπιδράσεις στο mock, δηλ. Η επικύρωση των κλήσεων προς τα πλαστά συνέβη σύμφωνα με τις προσδοκίες της υπό δοκιμή μεθόδου.
Με το Mocks, δεν χρειάζεται να κάνετε πολλές ρυθμίσεις, αλλά μπορείτε να επικυρώσετε τις αλληλεπιδράσεις που έγιναν με τα πλαστά αντικείμενα που παρέχονται στην υπό δοκιμή εφαρμογή.
Με χλευασμούς, μπορείτε να κάνετε πράγματα όπως:
- Με ποια επιχειρήματα κλήθηκαν οι χλευαστές;
- Ποιος ήταν ο συνολικός αριθμός των επίκλησης κλπ;
- Διασφάλιση της σειράς των χλευασμάτων.
Ας δούμε ένα απλό παράδειγμα του StudentGradeCalculator, όπου παρέχουμε το πλαστό αντικείμενο εφαρμογής βάσης δεδομένων και επικυρώνουμε τις αλληλεπιδράσεις με το Mock. Θα προσπαθήσουμε να κατανοήσουμε τις γελοίες δυνατότητες με απλά παραδείγματα.
Λάβετε υπόψη ότι όλες οι επικυρώσεις αλληλεπίδρασης πρέπει να πραγματοποιούνται στο μπλοκ 'τότε' κατά σύμβαση.
Παρακάτω είναι ο κωδικός για τη δοκιμαζόμενη μέθοδο (που θα καλείται στο « πότε: ' ΟΙΚΟΔΟΜΙΚΟ ΤΕΤΡΑΓΩΝΟ)
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) Επικύρωση των αλληλεπιδράσεων με ακριβή ορίσματα: Ας επικυρώσουμε πρώτα τις αλληλεπιδράσεις με τα ακριβώς αναμενόμενα ορίσματα. Εδώ θα περιμένουμε να κληθούν οι πλαστές μέθοδοι με τα ακριβή επιχειρήματα (σύμφωνα με τη ροή εκτέλεσης μεθόδου).
Εδώ ' μαθητήςΒάση δεδομένων 'Είναι το Mock μιας διεπαφής βάσης δεδομένων για την οποία επικυρώνουμε τις αλληλεπιδράσεις.
def 'illustrate mocks for interaction verification with arguments'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.updateStudentGrade('123','C') 1*studentDatabase.getStudentGrade('123') }
Όπως φαίνεται παραπάνω, επικυρώνουμε με τα ακριβή επιχειρήματα, έτσι ώστε η πλαστή εφαρμογή πρέπει να έχει ζητηθεί. Τυχόν αλλαγές σε αυτά τα ορίσματα θα προκαλέσουν την αποτυχία του τεστ και το αρχείο καταγραφής σφαλμάτων δείχνει τον κατάλληλο λόγο.
Ας προσπαθήσουμε να αλλάξουμε τον βαθμό σε ' ενημέρωσηStudentGrade 'To' A 'αντί για το πραγματικά' C 'και να δούμε τι λάθος λαμβάνουμε όταν εκτελείται η δοκιμή.
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')
Θα εμφανίσει ένα σφάλμα, όπως 'Πολύ λίγες προσκλήσεις', καθώς δεν μπορεί να βρει την επίκληση πλαστών με τα παρεχόμενα ορίσματα.
#δύο) Τώρα ας δούμε πώς να επικυρώσουμε τις αλληλεπιδράσεις Mock χωρίς να παρέχουμε τις πραγματικές τιμές ορίσματος, δηλαδή αυτό που μας ενδιαφέρει είναι απλώς να γνωρίζουμε ότι η πλαστή επικαλέστηκε τη μέθοδο αλλά όχι με ποια επιχειρήματα.
Αυτοί οι τύποι απαιτήσεων είναι πιο συνηθισμένοι κατά τη σύνταξη δοκιμών μονάδας για τον πραγματικό κωδικό παραγωγής, καθώς δεν είναι πάντα εύκολο να προσδιορίσετε τα πραγματικά επιχειρήματα που βασικά βασίζονται στην βασική επιχειρηματική λογική της υπό δοκιμή εφαρμογής.
Η σύνταξη είναι απλή, απλά πρέπει να χρησιμοποιήσετε μια υπογράμμιση '_' για ένα επιχείρημα όπου η πραγματική τιμή δεν είναι γνωστή.
Για παράδειγμα, για να ελέγξετε για οποιαδήποτε τιμή συμβολοσειράς, μπορείτε απλώς να αναφέρετε «_ Ως String Στη θέση ενός επιχειρήματος στη δοκιμή και θα πρέπει να περάσει για οποιαδήποτε τιμή συμβολοσειράς (παρόμοια για άλλους πρωτόγονους καθώς και προσαρμοσμένους τύπους δεδομένων).
Ας το καταλάβουμε με ένα παράδειγμα
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') }
Ένα σημαντικό σημείο που πρέπει να σημειωθεί εδώ είναι ότι μπορείτε πάντα να κάνετε mix και match για ποια επιχειρήματα είναι γνωστά και τι δεν είναι γνωστά. Για παράδειγμα, στο παρακάτω παράδειγμα, επικυρώνουμε την αλληλεπίδραση ενός πλαστή με τα πραγματικά επιχειρήματα και του άλλου με τους χαλαρούς ταιριαστές.
# 3) Τέλος, ας δούμε ένα σενάριο στο οποίο μπορούμε να εξακριβώσουμε τη σειρά της πλαστής επίκλησης, δηλαδή ποια σειρά κλήθηκαν οι χλευασμοί όταν εκτελείται η δοκιμή.
Μερικές φορές είναι απαραίτητο να επικυρωθεί η ροή των γεγονότων όταν υπάρχουν πολλοί συνεργάτες / χλευασμοί που εμπλέκονται στην υπό δοκιμή εφαρμογή και είναι χρήσιμο να κατανοήσουμε και να επικυρώσουμε ότι οι μέθοδοι κλήθηκαν με προκαθορισμένη σειρά.
def 'illustrate mocks for validating order'() { when: studentReportGenerator.calculateStudentGrade('123'); then: 1*studentDatabase.getStudentGrade('123') then: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) }
Αυτό μπορεί να επιτευχθεί χρησιμοποιώντας απλά πολλαπλά μπλοκ «τότε:» με τη σειρά των προσδοκιών ακολουθίας Mock. Εάν η αναφερθείσα ακολουθία δεν πληροί την πραγματική σειρά επίκλησης, τότε εμφανίζεται ένα σφάλμα που περιγράφει την 'Λάθος εντολή επίκλησης'
Για παράδειγμα, εάν αλλάξω τη σειρά των παραπάνω έπειτα δηλώσεις, η δοκιμαστική εκτέλεση θα ρίξει ένα σφάλμα όπως φαίνεται παρακάτω.
Wrong invocation order for: 1*studentDatabase.updateStudentGrade(_ as String, _ as String) (1 invocation) Last invocation: studentDatabase.updateStudentGrade('123', 'C')
Stubbing στο Spock
Εκπαιδευτικό βίντεο
Εξερευνήσαμε τα πάντα για το Mocking, ας δούμε τώρα πώς να ορίσουμε Stubs στα πλαστά αντικείμενα. Το Stubbing δεν είναι τίποτα άλλο από τη ρύθμιση προκαθορισμένων ή κονσερβοποιημένων απαντήσεων στις κλήσεις Mock για να δοκιμάσετε τις διαφορετικές ροές / σενάρια της υπό δοκιμή εφαρμογής.
Σκεφτείτε το ως προγραμματισμό μια πλαστή για να επιστρέψετε μια προκαθορισμένη τιμή όταν κλήθηκε. Θα συνεχίσουμε με την ίδια εφαρμογή StudentGradeCalculator και θα σταματήσουμε τις κλήσεις διεπαφής βάσης δεδομένων για να δοκιμάσουμε διαφορετικά σενάρια.
Ένα στέλεχος είναι σαν ένα χλευασμό που μιμείται κατά κάποιο τρόπο τη συμπεριφορά του πραγματικού αντικειμένου. Μπορείτε απλά να το ονομάσετε ως προγραμματισμένο χλευασμό.
Σύνταξη Stubbing
Η σύνταξη για το stubbing είναι 2 χειριστές δεξιάς μετατόπισης - δηλαδή ' >> '
Για να ορίσετε ένα στέλεχος σε οποιαδήποτε κλήση, μπορείτε να το ορίσετε ως εξής:
StubbedObject.StubbedMethod(//argumentList) >> “Stubbed Response”
Ας καταλάβουμε τώρα τα διαφορετικά σενάρια stubing με παραδείγματα.
# 1) Αντιγραφή με πραγματικές παραμέτρους: Εάν τα ορίσματα είναι γνωστά εκ των προτέρων ή αν θέλετε να ορίσετε stub μόνο όταν η επίκληση είναι με καθορισμένα ορίσματα, μπορεί να χρησιμοποιηθεί αυτός ο τρόπος καθορισμού stubs.
def 'illustrate stubs with exact matchers'() { given: studentDatabase.getStudentScores('123') >> (20F, 30F, 50F) when: def grade = studentReportGenerator.calculateStudentGrade('123') then: grade == 'A' }
Εδώ, μπορείτε να δείτε ότι το στέλεχος έχει οριστεί με ένα ακριβές όρισμα, δηλαδή το StudentId σε αυτήν την περίπτωση ως '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) }
Κατασκοπεία στο Spock
Οι κατάσκοποι βασίζονται σε πραγματικά αντικείμενα δηλαδή χρειάζονται την εφαρμογή διεπαφής και όχι την ίδια την αφηρημένη διεπαφή. Οι κατάσκοποι είναι ισχυροί και μπορούν να σας επιτρέψουν να λάβετε πραγματικές μεθόδους που απαιτούνται για την υπό δοκιμή εφαρμογή και να επαληθεύσετε ποια επιχειρήματα ζητήθηκαν οι μέθοδοι.
Οι κατάσκοποι επιτρέπουν επίσης τον ορισμό μερικών χλευασμάτων στις παρουσίες κατασκοπευτικών αντικειμένων. ας υποθέσουμε ότι θέλετε να ορίσετε τη συμπεριφορά ορισμένων μεθόδων στο αντικείμενο, τότε μπορείτε και επιτρέψτε στις υπόλοιπες να κληθούν ως κλήσεις πραγματικής μεθόδου.
Αυτά είναι συνήθως χρήσιμα σε μια κατάσταση όπου μπορεί να υπάρχουν ορισμένες μέθοδοι διεπαφής που δεν εφαρμόζονται και υπάρχουν μερικές άλλες που είναι πλήρως λειτουργικές. Ως εκ τούτου, εσείς ως προγραμματιστής μπορείτε να επιλέξετε να αποκόψετε τα μη υλοποιημένα και να καλέσετε τις πραγματικές υλοποιήσεις των λειτουργικών μεθόδων.
ποιο είναι το καλύτερο δωρεάν καθαριστικό μητρώου
Θα πρέπει να σημειωθεί ότι, για αντικείμενα Spied, εκτός αν έχουν οριστεί stubs, η προεπιλεγμένη συμπεριφορά θα είναι η κλήση της πραγματικής εφαρμογής. Τούτου λεχθέντος, οι κατάσκοποι δεν πρέπει να καλούνται συχνά και όλη η κάλυψη σεναρίων μπορεί να επιτευχθεί χρησιμοποιώντας χλευασμούς και στελέχη και έναν συνδυασμό αυτών.
Ας δούμε μερικά παραδείγματα χρησιμοποιώντας Spies στο πλαίσιο Spock χρησιμοποιώντας το ίδιο παράδειγμα του Υπολογιστής StudentGrade (Δημιουργήσαμε μια πραγματική εφαρμογή του Βάση δεδομένων σπουδαστών που είναι μια εφαρμογή στη μνήμη που χρησιμοποιεί HashMap για να απεικονίσει την κλήση πραγματικών μεθόδων και την επιστροφή δεδομένων. Ο κωδικός θα είναι διαθέσιμος στην τελευταία ενότητα του σεμιναρίου):
# 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' }
Το παραπάνω παράδειγμα απεικονίζει τη σύνταξη για τη δημιουργία Spy χρησιμοποιώντας το πλαίσιο Spock. Το στέλεχος ορίζεται κατά την ίδια τη στιγμή της δήλωσης.
Επίσης, οι κατασκοπευτικές κλήσεις μπορούν να επαληθευτούν όπως απεικονίζεται στο μπλοκ τότε (με χαλαρούς αντιστοιχιστές επιχειρημάτων που μπορούν να οριστούν για συγκεκριμένα επιχειρήματα).
# 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') }
Στο παραπάνω παράδειγμα, καθώς δεν έχουμε αναφερθεί καμιά συμπεριφορά, όλες οι κλήσεις θα μεταβούν στην πραγματική εφαρμογή.
συμπέρασμα
Σε αυτό το σεμινάριο, μάθαμε τα πάντα για τις ενσωματωμένες τεχνικές στο Mock Stub και το Spy χρησιμοποιώντας το πλαίσιο Spock. Το Spock το καθιστά εύκολο συνδυάζοντας αυτά τα χαρακτηριστικά ως μέρος του ίδιου του πλαισίου με μια πιο ευανάγνωστη σύνταξη groovy μαζί με τον μικρότερο κωδικό boilerplate.
Τα Mocks, Stubs και Spies χρησιμοποιούνται εκτενώς στις δοκιμές μονάδων για την αύξηση της κάλυψης και των δοκιμών ή την επικύρωση της βασικής επιχειρηματικής λογικής της υπό δοκιμή εφαρμογής.
Πηγαίος κώδικας για την εφαρμογή
StudentReportGenerator.java - αυτή είναι η μέθοδος / εφαρμογή υπό δοκιμή
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 - Διεπαφή βάσης δεδομένων
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 - Εφαρμογή μνήμης της διεπαφής 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); } }
Στο επερχόμενο σεμινάριό μας, θα δούμε πώς να ενσωματώσουμε το πλαίσιο Spock με άλλα δοκιμαστικά πλαίσια και τεχνολογίες.
Εκπαιδευτικό πρόγραμμα PREV | ΕΠΟΜΕΝΟ Φροντιστήριο
Συνιστώμενη ανάγνωση
- Γράφοντας μονάδες δοκιμών με Spock Framework
- Ερωτήσεις συνέντευξης Spock με απαντήσεις (πιο δημοφιλείς)
- Spock για ενσωμάτωση και λειτουργική δοκιμή με σελήνιο
- Με βάση δεδομένα ή παραμετρικές δοκιμές με πλαίσιο Spock
- Tutorial Spock: Δοκιμή με Spock και Groovy
- Καλύτερη δωρεάν σειρά C # Tutorial: Ο απόλυτος οδηγός C # για αρχάριους
- Φόρτωση δοκιμής με HP LoadRunner Tutorials
- Λειτουργίες ημερομηνίας και ώρας σε C ++ με παραδείγματα