mocking private static
Μάθετε τον Χλευασμό Ιδιωτικών, Στατικών και Άκυρων μεθόδων στο Mockito με Παραδείγματα:
Σε αυτήν τη σειρά πρακτικών Σεμινάρια για το Mockito , ρίξαμε μια ματιά στο διαφορετικοί τύποι Mockito Matchers στο τελευταίο σεμινάριο.
Σε γενικές γραμμές, η κοροϊδία ιδιωτικών και στατικών μεθόδων εμπίπτουν στην κατηγορία ασυνήθιστου κοροϊδισμού.
Εάν προκύψει ανάγκη να παραπλανηθούν οι ιδιωτικές και στατικές μέθοδοι / τάξεις, υποδηλώνει ότι ο κώδικας δεν έχει επαναδιαμορφωθεί και δεν είναι πραγματικά ένας ελεγχόμενος κώδικας και είναι πολύ πιθανό ότι κάποιος κώδικας παλαιού τύπου που δεν χρησιμοποιήθηκε για να είναι πολύ φιλικός προς τη μονάδα.
Τούτου λεχθέντος, εξακολουθεί να υπάρχει υποστήριξη για Mocking ιδιωτικές και στατικές μεθόδους από λίγα πλαίσια δοκιμών μονάδων όπως το PowerMockito (και όχι απευθείας από το Mockito).
Οι κοροϊδεύοντας 'άκυρες' μέθοδοι είναι συνηθισμένες, καθώς μπορεί να υπάρχουν μέθοδοι που ουσιαστικά δεν επιστρέφουν τίποτα, όπως η ενημέρωση μιας γραμμής βάσης δεδομένων (θεωρήστε τη ως λειτουργία PUT ενός τελικού σημείου Rest API που δέχεται μια είσοδο και δεν επιστρέφει καμία έξοδο).
Το Mockito παρέχει πλήρη υποστήριξη για τις πλαστές μεθόδους, οι οποίες θα δούμε με παραδείγματα σε αυτό το άρθρο.
υπολογιστής και επισκευή παραθύρων εργαλείων 10
Τι θα μάθετε:
- Powermock - Μια σύντομη εισαγωγή
- Χλευάσουμε ιδιωτικές μεθόδους
- Χλευάσουμε στατικές μεθόδους
- Μέθοδοι χλευάσματος
- ΣΥΜΒΟΥΛΕΣ
- συμπέρασμα
- Συνιστώμενη ανάγνωση
Powermock - Μια σύντομη εισαγωγή
Για τον Mockito, δεν υπάρχει άμεση υποστήριξη για την πλαστή ιδιωτική και στατική μέθοδο. Για να δοκιμάσετε ιδιωτικές μεθόδους, θα χρειαστεί αναπαράγει τον κωδικό για να αλλάξετε την πρόσβαση σε προστατευμένο (ή πακέτο) και θα πρέπει να αποφύγετε στατικές / τελικές μεθόδους.
Η Mockito, κατά τη γνώμη μου, σκόπιμα δεν παρέχει υποστήριξη για αυτά τα είδη χλευασμάτων, καθώς η χρήση αυτών των ειδών κώδικα κώδικα είναι μυρωδιές κώδικα και κακός σχεδιασμός κώδικα.
Όμως, υπάρχουν πλαίσια που υποστηρίζουν τη χλευασμό για ιδιωτικές και στατικές μεθόδους.
Powermock επεκτείνει τις δυνατότητες άλλων πλαισίων όπως το EasyMock και το Mockito και παρέχει τη δυνατότητα να πλαστογραφούν στατικές και ιδιωτικές μεθόδους.
# 1) Πώς: Το Powermock το κάνει αυτό με τη βοήθεια προσαρμοσμένου χειρισμού bytecode προκειμένου να υποστηρίξει τις πλαστές ιδιωτικές και στατικές μεθόδους, τις τελικές τάξεις, τους κατασκευαστές και ούτω καθεξής.
# 2) Υποστηριζόμενα πακέτα: Το Powermock παρέχει 2 API επέκτασης - ένα για το Mockito και ένα για το easyMock. Για χάρη αυτού του άρθρου, πρόκειται να γράψουμε παραδείγματα με την επέκταση Mockito για το mock mock.
# 3) Σύνταξη :Το Powermockito έχει μια σχεδόν παρόμοια σύνταξη με το Mockito, εκτός από ορισμένες πρόσθετες μεθόδους για την κοροϊδία στατικών και ιδιωτικών μεθόδων.
# 4) Ρύθμιση Powermockito
Προκειμένου να συμπεριληφθεί η βιβλιοθήκη Mockito σε έργα που βασίζονται σε διαβάθμιση, ακολουθούν οι βιβλιοθήκες που πρέπει να περιλαμβάνονται:
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4' testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
Παρόμοιες εξαρτήσεις είναι διαθέσιμες και για το maven.
Powermock-api-mockito2 - Η βιβλιοθήκη πρέπει να περιλαμβάνει επεκτάσεις Mockito για το Powermockito.
Powermock-module-junit4 - Η ενότητα απαιτείται για να περιλαμβάνει το PowerMockRunner (το οποίο είναι ένας προσαρμοσμένος δρομέας που χρησιμοποιείται για την εκτέλεση δοκιμών με το PowerMockito).
Ένα σημαντικό σημείο που πρέπει να σημειωθεί εδώ είναι ότι το PowerMock δεν υποστηρίζει τον δοκιμαστικό δρομέα Junit5. Ως εκ τούτου, οι δοκιμές πρέπει να γράφονται έναντι του Junit4 και οι δοκιμές πρέπει να εκτελούνται με το PowerMockRunner.
Για να χρησιμοποιήσετε το PowerMockRunner - η δοκιμαστική τάξη πρέπει να επισημαίνεται με @RunWith (PowerMockRunner.class)
Τώρα ας συζητήσουμε λεπτομερώς τις ιδιωτικές, στατικές και άκυρες μεθόδους!
Χλευάσουμε ιδιωτικές μεθόδους
Η χλευασμός ιδιωτικών μεθόδων, οι οποίες καλούνται εσωτερικά από μια υπό δοκιμή μέθοδο, μπορεί να είναι αναπόφευκτη σε συγκεκριμένες χρονικές στιγμές. Χρησιμοποιώντας το powermockito, αυτό είναι δυνατό και η επαλήθευση γίνεται χρησιμοποιώντας μια νέα μέθοδο με την ονομασία 'verifyPrivate'
Ας πάρουμε έναΠαράδειγμα όπου η υπό δοκιμή μέθοδος καλεί μια ιδιωτική μέθοδο (η οποία επιστρέφει ένα boolean). Προκειμένου να αποκοπεί αυτή η μέθοδος για να επιστρέψει true / false ανάλογα με τη δοκιμή, πρέπει να δημιουργηθεί ένα stub σε αυτήν την τάξη.
Για αυτό το Παράδειγμα, η υπό δοκιμή τάξη δημιουργείται ως κατάσκοπος παρουσίας με κοροϊδία σε λίγες προσκλήσεις διεπαφής και επίκληση ιδιωτικής μεθόδου.
Σημαντικά σημεία για Mock Private Method:
# 1) Η μέθοδος δοκιμής ή η τάξη δοκιμής πρέπει να επισημαίνονται με @ PrepareForTest (ClassUnderTest). Αυτός ο σχολιασμός λέει στο powerMockito να προετοιμάσει συγκεκριμένες κατηγορίες για δοκιμές.
Αυτά θα είναι ως επί το πλείστον εκείνα τα μαθήματα που πρέπει να είναι Το bytecode έχει υποστεί επεξεργασία . Συνήθως για τα τελικά μαθήματα, τάξεις που περιέχουν ιδιωτικές ή / και στατικές μεθόδους που πρέπει να κοροϊδεύονται κατά τη διάρκεια της δοκιμής.
Παράδειγμα:
@PrepareForTest(PriceCalculator.class)
#δύο) Για να ρυθμίσετε το stub σε μια ιδιωτική μέθοδο.
Σύνταξη - όταν (πλαστή ή κατάσκοπη παρουσία, 'privateMethodName'). thenReturn (// τιμή επιστροφής)
Παράδειγμα:
when (priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false);
# 3) Για να επαληθεύσετε την ιδιωτική μέθοδο που έχει διαγραφεί.
Σύνταξη - verifyPrivate (mockedInstance) .invoke ('privateMethodName')
Παράδειγμα:
verifyPrivate (priceCalculator).invoke('isCustomerAnonymous');
Πλήρες δείγμα δοκιμής: Συνεχίζοντας το ίδιο παράδειγμα από τα προηγούμενα άρθρα, όπου η τιμήCalculator έχει κάποιες πλαστές εξαρτήσεις όπως itemService, userService κ.λπ.
Δημιουργήσαμε μια νέα μέθοδο που ονομάζεται - calculPriceWithPrivateMethod, η οποία καλεί μια ιδιωτική μέθοδο μέσα στην ίδια τάξη και επιστρέφει εάν ο πελάτης είναι ανώνυμος ή όχι.
@Test @PrepareForTest(PriceCalculator.class) public void calculatePriceForAnonymous_witStubbedPrivateMethod_returnsCorrectPrice() throws Exception { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); double expectedPrice = 90.00; // Setting up stubbed responses using mocks when(priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false); when(mockedItemService.getItemDetails(123)).thenReturn(item1); // Act double actualDiscountedPrice = priceCalculatorSpy.calculatePriceWithPrivateMethod(123); // Assert verifyPrivate(priceCalculator).invoke('isCustomerAnonymous'); assertEquals(expectedPrice, actualDiscountedPrice); }
Χλευάσουμε στατικές μεθόδους
Οι στατικές μέθοδοι μπορούν να γελοιοποιηθούν με παρόμοιο τρόπο όπως είδαμε για τις ιδιωτικές μεθόδους.
Όταν μια υπό δοκιμή μέθοδος, περιλαμβάνει τη χρήση μιας στατικής μεθόδου από την ίδια τάξη (ή από διαφορετική τάξη), θα πρέπει να συμπεριλάβουμε αυτήν την κλάση στον σχολιασμό προετοιμασίας ForTest πριν από τη δοκιμή (ή στην τάξη δοκιμής).
Σημαντικά σημεία για Mock Static Methods:
# 1) Η μέθοδος δοκιμής ή η τάξη δοκιμής πρέπει να επισημαίνονται με @ PrepareForTest (ClassUnderTest). Παρόμοια με τις πλαστές ιδιωτικές μεθόδους / τάξεις, αυτό απαιτείται και για στατικές τάξεις.
#δύο) Ένα επιπλέον βήμα που απαιτείται για τις στατικές μεθόδους είναι - mockStatic (// όνομα στατικής τάξης)
Παράδειγμα:
mockStatic(DiscountCategoryFinder.class)
# 3) Το να εγκαταστήσετε το stub σε μια στατική μέθοδο, είναι εξίσου καλό με το stubing οποιασδήποτε μεθόδου σε οποιαδήποτε άλλη εικονική εμφάνιση διεπαφής / κλάσης.
Για παράδειγμα: Για να stub getDiscountCategory () (που επιστρέφει ένα enum DiscountCategory με τιμές PREMIUM & GENERAL) στατική μέθοδος της κατηγορίας DiscountCategoryFinder, απλώς κάντε stub ως εξής:
when (DiscountCategoryFinder. getDiscountCategory ()).thenReturn(DiscountCategory. PREMIUM );
# 4) Για την επαλήθευση της πλαστής ρύθμισης στην τελική / στατική μέθοδο, μπορεί να χρησιμοποιηθεί η μέθοδος VerifiedStatic ().
Παράδειγμα:
verifyStatic (DiscountCategoryFinder.class, times (1));
Μέθοδοι χλευάσματος
Ας προσπαθήσουμε πρώτα να καταλάβουμε τι είδους περιπτώσεις χρήσης ενδέχεται να περιλαμβάνουν μεθόδους κενών:
το καλύτερο spyware για κινητά τηλέφωνα
# 1) Για παράδειγμα, η μέθοδος κλήσεων - στέλνει ειδοποίηση μέσω email κατά τη διάρκεια της διαδικασίας.
Για παράδειγμα :Ας υποθέσουμε ότι αλλάζετε τον κωδικό πρόσβασής σας για τον τραπεζικό λογαριασμό σας στο Διαδίκτυο, όταν η αλλαγή είναι επιτυχής, λαμβάνετε ειδοποίηση μέσω του email σας.
Αυτό μπορεί να θεωρηθεί ως / changePassword ως κλήση POST προς το API της Τράπεζας που περιλαμβάνει μια κλήση άκυρης μεθόδου για την αποστολή ειδοποίησης μέσω email στον πελάτη.
#δύο) Ένα άλλο κοινό παράδειγμα της κλήσης με άκυρη μέθοδο είναι τα ενημερωμένα αιτήματα σε ένα DB που λαμβάνουν κάποια είσοδο και δεν επιστρέφουν τίποτα.
Οι μέθοδοι απομόνωσης κενών (δηλαδή οι μέθοδοι που δεν επιστρέφουν τίποτα, ή αλλιώς ρίχνουν μια εξαίρεση), μπορούν να αντιμετωπιστούν χρησιμοποιώντας συναρτήσεις doNothing (), doThrow () και doAnswer (), doCallRealMethod () . Απαιτεί το stub να ρυθμιστεί χρησιμοποιώντας τις παραπάνω μεθόδους σύμφωνα με τις προσδοκίες του τεστ.
Επίσης, λάβετε υπόψη ότι όλες οι κλήσεις άκυρης μεθόδου πλαστογραφούνται από προεπιλογή στο doNothing (). Ως εκ τούτου, ακόμη και αν δεν έχει πραγματοποιηθεί ρητή πλαστή ρύθμιση ΚΕΝΟΣ μέθοδος κλήσεις, η προεπιλεγμένη συμπεριφορά δεν έχει ακόμη γίνει Τίποτα ().
Ας δούμε παραδείγματα για όλες αυτές τις λειτουργίες:
Για όλα τα παραδείγματα, ας υποθέσουμε ότι υπάρχει τάξη Ενημερώσεις του StudentScore που έχει μια μέθοδο calculumSumAndStore (). Αυτή η μέθοδος υπολογίζει το άθροισμα των βαθμολογιών (ως είσοδος) και καλεί a κενός μέθοδος ενημέρωσηΣκορ () στην παρουσίαση βάσης δεδομένων.
public class StudentScoreUpdates { public IDatabase databaseImpl; public StudentScoreUpdates(IDatabase databaseImpl) { this.databaseImpl = databaseImpl; } public void calculateSumAndStore(String studentId, int() scores) { int total = 0; for(int score : scores) { total = total + score; } // write total to DB databaseImpl.updateScores(studentId, total); } }
Θα γράφουμε τεστ μονάδας για την πλαστή μέθοδο κλήσης με τα παρακάτω παραδείγματα:
# 1) doNothing () - doNothing () είναι η προεπιλεγμένη συμπεριφορά για κλήσεις με άκυρη μέθοδο στο Mockito, δηλ. Ακόμη και αν επαληθεύσετε μια μέθοδο κλήσης σε άκυρη (χωρίς να ρυθμίσετε ρητά ένα κενό για να κάνετε Τίποτα (), η επαλήθευση θα εξακολουθήσει να είναι επιτυχής)
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(anyString(), anyInt()); }
Άλλες χρήσεις μαζί με το doNothing ()
προς την) Όταν η μέθοδος άκυρου καλείται πολλές φορές και θέλετε να ρυθμίσετε διαφορετικές αποκρίσεις για διαφορετικές επίκληση, όπως - doNothing () για την πρώτη επίκληση και ρίξτε μια εξαίρεση στην επόμενη επίκληση.
Για παράδειγμα :Ρυθμίστε το mock ως εξής:
Mockito. doNothing ().doThrow(new RuntimeException()).when(mockDatabase).updateScores( anyString (), anyInt ());
σι) Όταν θέλετε να καταγράψετε τα επιχειρήματα με τα οποία κλήθηκε η μέθοδος άκυρου, θα πρέπει να χρησιμοποιηθεί η λειτουργικότητα ArgumentCaptor στο Mockito. Αυτό δίνει μια πρόσθετη επαλήθευση των επιχειρημάτων με τα οποία κλήθηκε η μέθοδος.
Παράδειγμα με το ArgumentCaptor:
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); ArgumentCaptor studentIdArgument = ArgumentCaptor.forClass(String.class); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(studentIdArgument.capture(), anyInt()); assertEquals('Student1', studentIdArgument.getValue()); }
# 2) doThrow ()- Αυτό είναι χρήσιμο όταν απλώς θέλετε να ρίξετε μια εξαίρεση όταν γίνεται επίκληση της μεθόδου άκυρου από την υπό δοκιμή μέθοδο.
Για παράδειγμα:
Mockito.doThrow(newRuntimeException()).when(mockDatabase).updateScores ( anyString (), anyInt ());
# 3) doAnswer ()- Το doAnswer () παρέχει απλώς μια διεπαφή για να κάνει κάποια προσαρμοσμένη λογική.
Π.χ. Τροποποίηση κάποιας τιμής μέσω των διαβιβαζόμενων ορισμάτων, επιστροφή προσαρμοσμένων τιμών / δεδομένων τα οποία δεν θα μπορούσε να επιστρέψει ένα κανονικό στέλεχος, ειδικά για μεθόδους άκυρου.
Για τους σκοπούς της επίδειξης - έκοψα την άκυρη μέθοδο updateScores () για να επιστρέψω ένα ' απάντηση() Και εκτυπώστε την τιμή ενός από τα ορίσματα που θα έπρεπε να είχαν περάσει όταν έπρεπε να κληθεί η μέθοδος.
Παράδειγμα κώδικα:
@Test public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabaseImpl); int() scores = {60,70,90}; Mockito.doCallRealMethod().when(mockDatabaseImpl).updateScores(anyString(), anyInt()); doAnswer(invocation -> { Object() args = invocation.getArguments(); Object mock = invocation.getMock(); System.out.println(args(0)); return mock; }).when(mockDatabaseImpl).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabaseImpl, Mockito.times(1)).updateScores(anyString(), anyInt()); }
# 4) doCallRealMethod ()- Μερικές χλευές είναι παρόμοιες με τα στέλεχος (όπου μπορείτε να καλέσετε πραγματικές μεθόδους για ορισμένες από τις μεθόδους και να απομακρύνετε τις υπόλοιπες).
Για άκυρες μεθόδους, το mockito παρέχει μια ειδική λειτουργία που ονομάζεται doCallRealMethod () η οποία μπορεί να χρησιμοποιηθεί όταν προσπαθείτε να ρυθμίσετε το mock. Αυτό που θα κάνει, είναι να καλέσετε τη μέθοδο πραγματικού κενού με τα πραγματικά επιχειρήματα.
Για παράδειγμα:
Mockito. doCallRealMethod ().when(mockDatabaseImpl).updateScores( anyString (), anyInt ());
ΣΥΜΒΟΥΛΕΣ
# 1) Συμπερίληψη πολλαπλών στατικών τάξεων στην ίδια μέθοδο / τάξη δοκιμής- Χρησιμοποιώντας το PowerMockito αν υπάρχει ανάγκη να Χλευάσουμε πολλά μαθήματα Στατικών Τελικών τότε τα ονόματα των τάξεων στο @ PrepareForTest Ο σχολιασμός μπορεί να αναφέρεται ως τιμή διαχωρισμένη με κόμμα ως πίνακας (ουσιαστικά δέχεται έναν πίνακα από τα ονόματα τάξεων).
Παράδειγμα:
@PrepareForTest({PriceCalculator.class, DiscountCategoryFinder.class})
Όπως φαίνεται στο παραπάνω παράδειγμα, υποθέστε ότι το PriceCalculator και το DiscountCategoryFinder είναι τελικές τάξεις που πρέπει να κοροϊδευτούν. Και τα δύο αυτά μπορούν να αναφερθούν ως μια σειρά από τάξεις στο σχολιασμό PrepareForTest και μπορούν να κοπούν στη μέθοδο δοκιμής.
# 2) Θέση χαρακτηριστικού PrepareForTest - Η τοποθέτηση αυτού του χαρακτηριστικού είναι σημαντική όσον αφορά το είδος των δοκιμών που περιλαμβάνονται στην τάξη δοκιμών.
Εάν όλες οι δοκιμές πρέπει να χρησιμοποιούν την ίδια τελική τάξη, τότε είναι λογικό να αναφέρουμε αυτό το χαρακτηριστικό σε επίπεδο τάξης δοκιμής που σημαίνει απλά ότι η προετοιμασμένη τάξη θα είναι διαθέσιμη σε όλες τις μεθόδους δοκιμής. Σε αντίθεση με αυτό, εάν ο σχολιασμός αναφέρεται στη μέθοδο δοκιμής, τότε θα είναι διαθέσιμος μόνο για τις συγκεκριμένες δοκιμές
συμπέρασμα
Σε αυτό το σεμινάριο, συζητήσαμε διάφορες προσεγγίσεις για πλαστές στατικές, τελικές και άκυρες μεθόδους.
Παρόλο που η χρήση πολλών στατικών ή τελικών μεθόδων εμποδίζει τη δυνατότητα δοκιμής, και παρόλα αυτά, υπάρχει διαθέσιμη υποστήριξη για δοκιμές / κοροϊδεύσεις για να βοηθήσει στη δημιουργία δοκιμών μονάδας προκειμένου να επιτευχθεί μεγαλύτερη εμπιστοσύνη στον κώδικα / εφαρμογή ακόμη και για κώδικα παλαιού τύπου που δεν χρησιμοποιείται συνήθως για να είναι σχεδιασμένο για δοκιμή.
Για στατικές και τελικές μεθόδους, το Mockito δεν διαθέτει υποστήριξη εκτός κουτιού, αλλά βιβλιοθήκες όπως το PowerMockito (που κληρονομούν σε μεγάλο βαθμό πολλά πράγματα από το Mockito) παρέχουν τέτοια υποστήριξη και πρέπει πραγματικά να εκτελέσουν χειρισμό bytecode για να υποστηρίξουν αυτές τις δυνατότητες.
Το Mockito out of the box υποστηρίζει μεθόδους απομόνωσης και παρέχει διάφορες μεθόδους όπως doNothing, doAnswer, doThrow, doCallRealMethod κ.λπ. και μπορεί να χρησιμοποιηθεί σύμφωνα με την απαίτηση του τεστ.
Οι περισσότερες συχνές ερωτήσεις συνέντευξης Mockito αναφέρονται στο επόμενο σεμινάριό μας.
Εκπαιδευτικό πρόγραμμα PREV | ΕΠΟΜΕΝΟ Φροντιστήριο
Συνιστώμενη ανάγνωση
- Εκπαιδευτικό Mockito: Mockito Framework για χλευασμό σε δοκιμές μονάδας
- Κορυφαίες 12 ερωτήσεις συνέντευξης Mockito (Συνέντευξη Mocking Framework)
- Στατικό σε C ++
- Νήματα Java με μεθόδους και κύκλο ζωής
- Δημιουργία χλευασμάτων και κατασκόπων στο Mockito με παραδείγματα κώδικα
- Διαφορετικοί τύποι αντιστοιχιών που παρέχονται από τον Mockito
- Μέθοδοι και τεχνικές πρόληψης ελαττωμάτων
- Τρόπος χρήσης μεθόδων στο SoapUI για μαζική εκτέλεση δοκιμών - SoapUI Tutorial # 10