mocking private static
Apprenez à se moquer des méthodes privées, statiques et nulles dans Mockito avec des exemples:
Dans cette série de travaux pratiques Tutoriels sur Mockito , nous avons regardé le différents types de Mockito Matchers dans le dernier tutoriel.
D'une manière générale, les moqueries des méthodes privées et statiques relèvent de la catégorie des moqueries inhabituelles.
Si le besoin se fait sentir de se moquer de méthodes / classes privées et statiques, cela indique un code mal refactorisé et n'est pas vraiment un code testable et il est très probable que certains codes hérités qui n'étaient pas utilisés pour être très conviviaux pour les tests unitaires.
Cela dit, il existe toujours un support pour les méthodes privées et statiques Mocking par quelques frameworks de test unitaire comme PowerMockito (et pas directement par Mockito).
Les méthodes moqueuses «void» sont courantes car il peut y avoir des méthodes qui ne renvoient essentiellement rien, comme la mise à jour d'une ligne de base de données (considérez-la comme une opération PUT d'un point de terminaison d'API Rest qui accepte une entrée et ne renvoie aucune sortie).
Mockito fournit un support complet pour les méthodes vides moqueuses, que nous verrons avec des exemples dans cet article.
questions d'entrevue de test de logiciel pour expérimentés
Ce que vous apprendrez:
- Powermock - Une brève introduction
- Se moquer des méthodes privées
- Mocking Static Methods
- Mocking Void Methods
- Conseils & Astuces
- Conclusion
- lecture recommandée
Powermock - Une brève introduction
Pour Mockito, il n'y a pas de support direct pour simuler les méthodes privées et statiques. Afin de tester des méthodes privées, vous devrez refactoriser le code pour changer l'accès à protected (ou package) et vous devrez éviter les méthodes statiques / finales.
Mockito, à mon avis, ne fournit pas intentionnellement de support pour ces types de simulations, car l'utilisation de ces types de constructions de code sont des odeurs de code et du code mal conçu.
Mais, il existe des frameworks qui prennent en charge la simulation pour les méthodes privées et statiques.
Powermock étend les capacités d'autres frameworks comme EasyMock et Mockito et offre la possibilité de simuler des méthodes statiques et privées.
# 1) Comment: Powermock le fait à l'aide d'une manipulation de bytecode personnalisée afin de prendre en charge les méthodes privées et statiques moqueuses, les classes finales, les constructeurs, etc.
# 2) Paquets pris en charge: Powermock fournit 2 API d'extension - une pour Mockito et une pour easyMock. Pour le bien de cet article, nous allons écrire des exemples avec l'extension Mockito pour power mock.
# 3) Syntaxe :Powermockito a une syntaxe presque similaire à celle de Mockito, à l'exception de quelques méthodes supplémentaires pour se moquer des méthodes statiques et privées.
# 4) Configuration de Powermockito
Afin d'inclure la bibliothèque Mockito dans les projets basés sur gradle, voici les bibliothèques à inclure:
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4' testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
Des dépendances similaires sont également disponibles pour maven.
Powermock-api-mockito2 - La bibliothèque doit inclure les extensions Mockito pour Powermockito.
Powermock-module-junit4 - Le module doit inclure PowerMockRunner (qui est un exécuteur personnalisé à utiliser pour exécuter des tests avec PowerMockito).
Un point important à noter ici est que PowerMock ne prend pas en charge le lanceur de test Junit5. Par conséquent, les tests doivent être écrits sur Junit4 et les tests doivent être exécutés avec PowerMockRunner.
Pour utiliser PowerMockRunner - la classe de test doit être annotée avec @RunWith (PowerMockRunner.class)
Parlons maintenant des méthodes privées, statiques et nulles en détail!
Se moquer des méthodes privées
Se moquer des méthodes privées, appelées en interne à partir d'une méthode testée, peut être inévitable à certains moments. En utilisant powermockito, cela est possible et la vérification est effectuée à l'aide d'une nouvelle méthode nommée «verifyPrivate»
Prenons uneExemple où la méthode sous test appelle une méthode privée (qui renvoie un booléen). Afin de stub cette méthode pour retourner vrai / faux en fonction du test, un stub doit être mis en place sur cette classe.
Pour cet exemple, la classe testée est créée en tant qu'instance d'espionnage avec moquerie sur quelques appels d'interface et invocation de méthode privée.
Points importants de la méthode privée simulée:
#1) La méthode de test ou la classe de test doit être annotée avec @ PréparerForTest (ClassUnderTest). Cette annotation indique à powerMockito de préparer certaines classes pour les tests.
Ce seront principalement les classes qui doivent être Bytecode manipulé . En règle générale, pour les classes finales, les classes contenant des méthodes privées et / ou statiques qui doivent être simulées pendant les tests.
Exemple:
@PrepareForTest(PriceCalculator.class)
#deux) Pour configurer le stub sur une méthode privée.
Syntaxe - when (instance fictive ou espion, 'privateMethodName'). thenReturn (// valeur de retour)
Exemple:
when (priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false);
# 3) Pour vérifier la méthode privée stubbed.
Syntaxe - verifyPrivate (mockedInstance) .invoke («privateMethodName»)
Exemple:
verifyPrivate (priceCalculator).invoke('isCustomerAnonymous');
Échantillon de test complet: Poursuivant le même exemple des articles précédents, où priceCalculator a des dépendances simulées comme itemService, userService, etc.
Nous avons créé une nouvelle méthode appelée - CalculatePriceWithPrivateMethod, qui appelle une méthode privée à l'intérieur de la même classe et renvoie si le client est anonyme ou non.
@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); }
Mocking Static Methods
Les méthodes statiques peuvent être simulées de la même manière que nous l'avons vu pour les méthodes privées.
Lorsqu'une méthode testée implique l'utilisation d'une méthode statique de la même classe (ou d'une classe différente), nous devrons inclure cette classe dans l'annotation prepareForTest avant le test (ou sur la classe test).
Points importants des méthodes statiques simulées:
#1) La méthode de test ou la classe de test doit être annotée avec @ PréparerForTest (ClassUnderTest). Semblable à la simulation de méthodes / classes privées, cela est également nécessaire pour les classes statiques.
#deux) Une étape supplémentaire requise pour les méthodes statiques est - mockStatic (// nom de la classe statique)
Exemple:
mockStatic(DiscountCategoryFinder.class)
# 3) Configurer le stub sur une méthode statique est aussi bon que le stub de n'importe quelle méthode sur n'importe quelle autre instance de simulation d'interface / classe.
Par exemple: Pour stub getDiscountCategory () (qui renvoie une énumération DiscountCategory avec des valeurs PREMIUM & GENERAL) la méthode statique de la classe DiscountCategoryFinder, stub simplement comme suit:
when (DiscountCategoryFinder. getDiscountCategory ()).thenReturn(DiscountCategory. PREMIUM );
# 4) Pour vérifier la configuration fictive sur la méthode finale / statique, la méthode verifyStatic () peut être utilisée.
Exemple:
verifyStatic (DiscountCategoryFinder.class, times (1));
Mocking Void Methods
Essayons d'abord de comprendre quels types de cas d'utilisation peuvent impliquer des méthodes vides de remplacement:
#1) Appels de méthode par exemple - qui envoie une notification par e-mail pendant le processus.
merge sort c ++ récursif
Par exemple :Supposons que vous modifiez votre mot de passe pour votre compte bancaire Internet, une fois la modification réussie, vous recevez une notification par e-mail.
Cela peut être considéré comme / changePassword comme un appel POST à l'API Bank qui comprend un appel de méthode void pour envoyer une notification par e-mail au client.
#deux) Un autre exemple courant de l'appel de méthode void est celui des requêtes mises à jour à une base de données qui prennent une entrée et ne renvoient rien.
Les méthodes void stubbing (c'est-à-dire les méthodes qui ne retournent rien, ou qui lancent une exception), peuvent être gérées en utilisant fonctions doNothing (), doThrow () et doAnswer (), doCallRealMethod () . Il nécessite que le stub soit configuré en utilisant les méthodes ci-dessus conformément aux attentes du test.
Notez également que tous les appels de méthode void sont par défaut simulés par doNothing (). Par conséquent, même si une configuration fictive explicite n'est pas effectuée sur ANNULER appels de méthode, le comportement par défaut est toujours de doNothing ().
Voyons des exemples pour toutes ces fonctions:
Pour tous les exemples, supposons qu'il existe une classe StudentScoreMises à jour qui a une méthode calculerSumAndStore (). Cette méthode calcule la somme des scores (en entrée) et appelle un annuler méthode updateScores () sur une instance de databaseImplementation.
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); } }
Nous allons écrire des tests unitaires pour l'appel de méthode simulée avec les exemples ci-dessous:
# 1) ne rien faire () - doNothing () est le comportement par défaut pour les appels de méthode void dans Mockito, c'est-à-dire même si vous vérifiez un appel sur la méthode void (sans configurer explicitement un void pour doNothing (), la vérification sera toujours réussie)
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()); }
Autres usages avec doNothing ()
à) Lorsque la méthode void est appelée plusieurs fois et que vous souhaitez configurer différentes réponses pour différentes invocations, comme - doNothing () pour le premier appel et lever une exception lors du prochain appel.
Par exemple :Configurez une maquette comme ceci:
Mockito. doNothing ().doThrow(new RuntimeException()).when(mockDatabase).updateScores( anyString (), anyInt ());
b) Lorsque vous souhaitez capturer les arguments avec lesquels la méthode void a été appelée, la fonctionnalité ArgumentCaptor de Mockito doit être utilisée. Cela donne une vérification supplémentaire des arguments avec lesquels la méthode a été appelée.
Exemple avec 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 ()- Ceci est utile lorsque vous souhaitez simplement lever une exception lorsque la méthode void est appelée à partir de la méthode testée.
Par exemple:
Mockito.doThrow(newRuntimeException()).when(mockDatabase).updateScores ( anyString (), anyInt ());
# 3) doAnswer ()- doAnswer () fournit simplement une interface pour faire une logique personnalisée.
Par exemple. Modifier une valeur via les arguments passés, renvoyer des valeurs / données personnalisées qu'un stub normal n'aurait pas pu renvoyer, en particulier pour les méthodes void.
À des fins de démonstration, j'ai stubé la méthode void updateScores () pour renvoyer un ' répondre() »Et affiche la valeur de l'un des arguments qui aurait dû être passé lorsque la méthode aurait dû être appelée.
Exemple de code:
@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 ()- Les simulations partielles sont similaires aux stubs (où vous pouvez appeler de vraies méthodes pour certaines des méthodes et supprimer le reste).
Pour les méthodes void, mockito fournit une fonction spéciale appelée doCallRealMethod () qui peut être utilisée lorsque vous essayez de configurer la maquette. Ce que cela fera, c'est d'appeler la méthode real void avec les arguments réels.
Par exemple:
Mockito. doCallRealMethod ().when(mockDatabaseImpl).updateScores( anyString (), anyInt ());
Conseils & Astuces
# 1) Inclure plusieurs classes statiques dans la même méthode / classe de test- Utilisation de PowerMockito s'il est nécessaire de simuler plusieurs classes statiques de finales, les noms de classe dans @ PréparerForTest l'annotation peut être mentionnée comme une valeur séparée par des virgules sous forme de tableau (elle accepte essentiellement un tableau des noms de classe).
Exemple:
@PrepareForTest({PriceCalculator.class, DiscountCategoryFinder.class})
Comme indiqué dans l'exemple ci-dessus, supposons que PriceCalculator et DiscountCategoryFinder sont des classes finales qui doivent être simulées. Ces deux éléments peuvent être mentionnés comme un tableau de classes dans l'annotation PrepareForTest et peuvent être stubbed dans la méthode de test.
# 2) Positionnement des attributs PrepareForTest - Le positionnement de cet attribut est important en ce qui concerne le type de tests inclus dans la classe Test.
Si tous les tests doivent utiliser la même classe finale, il est logique de mentionner cet attribut au niveau de la classe de test, ce qui signifie simplement que la classe préparée sera disponible pour toutes les méthodes de test. Par opposition à cela, si l'annotation est mentionnée dans la méthode de test, elle ne sera disponible que pour ces tests particuliers
Conclusion
Dans ce didacticiel, nous avons discuté de diverses approches pour simuler les méthodes statiques, finales et vides.
Bien que l'utilisation de nombreuses méthodes statiques ou finales entrave la testabilité, il existe néanmoins un support disponible pour les tests / simulations pour aider à créer des tests unitaires afin d'obtenir une plus grande confiance dans le code / l'application, même pour le code hérité qui n'est généralement pas utilisé pour être conçu pour la testabilité.
Pour les méthodes statiques et finales, Mockito n'a pas de support prêt à l'emploi, mais des bibliothèques comme PowerMockito (qui héritent fortement de beaucoup de choses de Mockito) fournissent un tel support et doivent en fait effectuer une manipulation de bytecode afin de prendre en charge ces fonctionnalités.
Mockito prêt à l'emploi prend en charge les méthodes de stubbing void et fournit diverses méthodes telles que doNothing, doAnswer, doThrow, doCallRealMethod, etc. et peut être utilisé selon les exigences du test.
Les questions d'entrevue Mockito les plus fréquemment posées sont présentées dans notre prochain tutoriel.
Tutoriel PREV | Tutoriel SUIVANT
lecture recommandée
- Tutoriel Mockito: Framework Mockito pour la simulation dans les tests unitaires
- Top 12 des questions d'entrevue Mockito (entretien Mocking Framework)
- Statique en C ++
- Threads Java avec méthodes et cycle de vie
- Créer des simulacres et des espions dans Mockito avec des exemples de code
- Différents types de matchers fournis par Mockito
- Méthodes et techniques de prévention des défauts
- Comment utiliser des méthodes dans SoapUI pour l'exécution de tests en masse - Tutoriel SoapUI # 10