Introduction à PowerMock

1. Vue d'ensemble

Les tests unitaires à l'aide d'un cadre moqueur sont reconnus comme une pratique utile depuis longtemps, et le cadre Mockito, en particulier, a dominé ce marché ces dernières années.

Et afin de faciliter la conception de code décent et de simplifier l'API publique, certaines fonctionnalités souhaitées ont été intentionnellement laissées de côté. Dans certains cas, cependant, ces lacunes obligent les testeurs à écrire du code encombrant juste pour rendre la création de simulations possible.

C'est là que le framework PowerMock entre en jeu.

PowerMockito est une API d'extension de PowerMock pour prendre en charge Mockito. Il fournit des capacités pour travailler avec l'API Java Reflection d'une manière simple pour surmonter les problèmes de Mockito, tels que le manque de capacité à se moquer des méthodes finales, statiques ou privées.

Ce tutoriel donnera une introduction à l'API PowerMockito et à son application dans les tests.

2. Préparation aux tests avec PowerMockito

La première étape pour intégrer la prise en charge de PowerMock pour Mockito consiste à inclure les deux dépendances suivantes dans le fichier Maven POM:

 org.powermock powermock-module-junit4 1.6.4 test   org.powermock powermock-api-mockito 1.6.4 test 

Ensuite, nous devons préparer nos cas de test pour travailler avec PowerMockito en appliquant les deux annotations suivantes:

@RunWith(PowerMockRunner.class) @PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")

L' élément FullyQualifiedNames dans l' annotation @PrepareForTest représente un tableau de noms complets de types que nous voulons simuler. Dans ce cas, nous utilisons un nom de package avec un caractère générique pour indiquer à PowerMockito de préparer tous les types du package com.baeldung.powermockito.introduction pour la moquerie.

Nous sommes maintenant prêts à exploiter la puissance de PowerMockito .

3. Constructeurs moqueurs et méthodes finales

Dans cette section, nous montrerons les moyens d'obtenir une instance fictive au lieu d'une instance réelle lors de l'instanciation d'une classe avec le nouvel opérateur, puis utiliserons cet objet pour simuler une méthode finale. La classe collaboratrice, dont les constructeurs et les méthodes finales seront simulés, est définie comme suit:

public class CollaboratorWithFinalMethods { public final String helloMethod() { return "Hello World!"; } }

Tout d'abord, nous créons un objet fictif à l'aide de l' API PowerMockito :

CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);

Ensuite, définissez une attente indiquant que chaque fois que le constructeur sans argument de cette classe est invoqué, une instance fictive doit être renvoyée plutôt qu'une vraie:

whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);

Voyons comment cette simulation de construction fonctionne en action en instanciant la classe CollaboratorWithFinalMethods à l' aide de son constructeur par défaut, puis vérifions les comportements de PowerMock:

CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods(); verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();

À l'étape suivante, une attente est définie sur la méthode finale:

when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");

Cette méthode est ensuite exécutée:

String welcome = collaborator.helloMethod();

Les assertions suivantes confirment que la méthode helloMethod a été appelée sur l' objet collaborator et renvoie la valeur définie par l'attente moqueuse:

Mockito.verify(collaborator).helloMethod(); assertEquals("Hello Baeldung!", welcome);

Si nous voulons nous moquer d'une méthode finale spécifique plutôt que de toutes les dernières à l'intérieur d'un objet, la méthode Mockito.spy (objet T) peut être utile. Ceci est illustré dans la section 5.

4. Méthodes statiques moqueuses

Supposons que nous souhaitons simuler des méthodes statiques d'une classe nommée CollaboratorWithStaticMethods. Cette classe est déclarée comme suit:

public class CollaboratorWithStaticMethods { public static String firstMethod(String name) { return "Hello " + name + " !"; } public static String secondMethod() { return "Hello no one!"; } public static String thirdMethod() { return "Hello no one again!"; } }

Afin de simuler ces méthodes statiques, nous devons enregistrer la classe englobante avec l' API PowerMockito :

mockStatic(CollaboratorWithStaticMethods.class);

Alternativement, nous pouvons utiliser la méthode Mockito.spy (classe de classe) pour simuler une méthode spécifique, comme illustré dans la section suivante.

Ensuite, les attentes peuvent être définies pour définir les valeurs que les méthodes doivent renvoyer lorsqu'elles sont appelées:

when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString())) .thenReturn("Hello Baeldung!"); when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");

Ou une exception peut être définie pour être levée lors de l'appel de la méthode thirdMethod :

doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class); CollaboratorWithStaticMethods.thirdMethod();

Maintenant, il est temps d'exécuter les deux premières méthodes:

String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever"); String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");

Au lieu d'appeler des membres de la classe réelle, les appels ci-dessus sont délégués aux méthodes de la simulation. Les affirmations suivantes prouvent que le simulacre est entré en vigueur:

assertEquals("Hello Baeldung!", firstWelcome); assertEquals("Hello Baeldung!", secondWelcome);

Nous sommes également en mesure de vérifier les comportements des méthodes de simulation, y compris le nombre de fois qu'une méthode est invoquée. Dans ce cas, le firstMethod a été appelé deux fois, tandis que le secondMethod n'a jamais:

verifyStatic(Mockito.times(2)); CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()); verifyStatic(Mockito.never()); CollaboratorWithStaticMethods.secondMethod();

Remarque: La méthode verifyStatic doit être appelée juste avant toute vérification de méthode statique pour que PowerMockito sache que l'appel de méthode successive est ce qui doit être vérifié.

Lastly, the static thirdMethod method should throw a RuntimeException as declared on the mock before. It is validated by the expected element of the @Test annotation:

@Test(expected = RuntimeException.class) public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() { // other methods CollaboratorWithStaticMethods.thirdMethod(); }

5. Partial Mocking

Instead of mocking an entire class, the PowerMockito API allows for mocking part of it using the spy method. The following class will be used as the collaborator to illustrate the PowerMock support for partial mocking:

public class CollaboratorForPartialMocking { public static String staticMethod() { return "Hello Baeldung!"; } public final String finalMethod() { return "Hello Baeldung!"; } private String privateMethod() { return "Hello Baeldung!"; } public String privateMethodCaller() { return privateMethod() + " Welcome to the Java world."; } }

Let's begin with mocking a static method, which is named staticMethod in the above class definition. First, use the PowerMockito API to partially mock the CollaboratorForPartialMocking class and set an expectation for its static method:

spy(CollaboratorForPartialMocking.class); when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");

The static method is then executed:

returnValue = CollaboratorForPartialMocking.staticMethod();

The mocking behavior is verified as follows:

verifyStatic(); CollaboratorForPartialMocking.staticMethod();

The following assertion confirms that the mock method has actually been called by comparing the return value against the expectation:

assertEquals("I am a static mock method.", returnValue);

Now it is time to move on to the final and private methods. In order to illustrate the partial mocking of these methods, we need to instantiate the class and tell the PowerMockito API to spy it:

CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking(); CollaboratorForPartialMocking mock = spy(collaborator);

The objects created above are used to demonstrating the mocking of both the final and private methods. We will deal with the final method now by setting an expectation and invoke the method:

when(mock.finalMethod()).thenReturn("I am a final mock method."); returnValue = mock.finalMethod();

The behavior of partially mocking that method is proved:

Mockito.verify(mock).finalMethod();

A test verifies that calling the finalMethod method will return a value that matches the expectation:

assertEquals("I am a final mock method.", returnValue);

A similar process is applied to the private method. The main difference is that we cannot directly invoke this method from the test case. Basically, a private method is to be called by other ones from the same class. In the CollaboratorForPartialMocking class, the privateMethod method is to be invoked by the privateMethodCaller method and we will use the latter as a delegate. Let's start with the expectation and invocation:

when(mock, "privateMethod").thenReturn("I am a private mock method."); returnValue = mock.privateMethodCaller();

The mocking of the private method is confirmed:

verifyPrivate(mock).invoke("privateMethod");

The following test makes sure that the return value from invocation of the private method is the same as the expectation:

assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);

6. Conclusion

Ce didacticiel a fourni une introduction à l' API PowerMockito , démontrant son utilisation pour résoudre certains des problèmes rencontrés par les développeurs lors de l'utilisation du framework Mockito.

L'implémentation de ces exemples et extraits de code se trouve dans le projet GitHub lié.