Se moquant de variables membres d'une classe à l'aide de Mockito
Je suis un newbie dans le développement et les tests unitaires en particulier .
Je suppose que ma demande est assez simple, mais je suis curieux de savoir d'autres idées à ce sujet.
Supposons que j'ai deux classes comme le
public class First {
Second second ;
public First(){
second = new Second();
}
public String doSecond(){
return second.doSecond();
}
}
class Second {
public String doSecond(){
return "Do Something";
}
}
Disons que je suis d'écriture de l'unité de test pour tester First.doSecond()
méthode. Cependant, supposons que, je veux Maquette Second.doSecond()
classe comme si. Je suis à l'aide de Mockito pour ce faire.
public void testFirst(){
Second sec = mock(Second.class);
when(sec.doSecond()).thenReturn("Stubbed Second");
First first = new First();
assertEquals("Stubbed Second", first.doSecond());
}
Je vois que les moqueries ne prend pas effet et l'assertion échoue.
Il n'y a aucune façon de se moquer des variables membres d'une classe que je veux tester . ?
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin de fournir un moyen d'accéder à des variables de membre de sorte que vous pouvez passer à une simulation (les façons les plus courantes serait un poseur de méthode ou d'un constructeur qui prend un paramètre).
Si votre code ne fournit pas un moyen de le faire, il est correctement compte pour le TDD (Test Driven Development).
Ce n'est pas possible si vous ne pouvez pas modifier votre code. Mais j'ai comme l'injection de dépendance et Mockito prend en charge:
Votre test:
C'est très agréable et facile.
Si vous regardez de près votre code, vous verrez que le
second
propriété dans votre test est toujours une instance deSecond
, pas un simulacre (vous ne passez pas le simulacre defirst
dans votre code).La façon la plus simple serait de créer un setter pour
second
dansFirst
classe et la passer à la maquette explicitement.Comme ceci:
Une autre serait de passer un
Second
instanceFirst
's paramètre du constructeur.Si vous ne pouvez pas modifier le code, je pense que la seule option serait d'utiliser la réflexion:
Mais vous pouvez probablement, comme il est rare de faire des tests sur le code, vous n'avez pas le contrôle (même si on peut imaginer un scénario où vous avez pour tester une bibliothèque externe car il est auteur ne l'a pas :))
@Mock
et l'annoter, d'Abord avec@InjectMocks
et instancier Première dans l'initialiseur. Mockito fera automatiquement, il est préférable de trouver un endroit pour s'injecter de la Deuxième maquette en Première instance, y compris la configuration des champs privés que le type de correspondance.@Mock
était d'environ 1,5 (peut-être plus tôt, je ne suis pas sûr). 1.8.3 introduit@InjectMocks
ainsi que@Spy
et@Captor
.First
, dans lequel vous pouvez passer à laSecond
. Vous pouvez même rendre public l'appel du constructeur le colis-privé avecthis( new Second());
. Puis à l'intérieur de votre test, appelez le colis-privé constructeur lorsque vous faites l'objet du test.@InjectMocks
beaucoup, car il ne fonctionne pas dans tous les cas. Il va travailler pour cet exemple particulier, mais si il y a un constructeur qui peut être utilisé pour le constructeur d'injection (et il y a de tout à fait logique complexe autour de cela), alors@InjectMocks
ne vais pas essayer domaine de l'injection, et le test ne fonctionne pas. Je préfère éviter les@InjectMocks
entièrement, à cause de ses incohérences apparentes (et oui, je me rends compte que ce n'est pas incompatible si vous comprendre sa logique tout à fait; mais je ne pense pas que cela vaille la peine de s'en occuper).Si vous ne pouvez pas modifier la variable membre, puis l'autre façon de contourner cela est d'utiliser powerMockit et appel
Maintenant, le problème est que TOUT appel à la nouvelle Seconde sera de retour le même moqué d'instance. Mais dans votre cas simple cela fonctionne.
J'ai eu le même problème où une valeur privée n'a pas été réglée parce que Mockito n'appelle pas super constructeurs. Voici comment j'ai augmenter moqueur avec la réflexion.
Tout d'abord, j'ai créé un TestUtils classe qui contient de nombreux utilitaires dont ces méthodes de réflexion. La réflexion de l'accès est un peu bancale à mettre en œuvre à chaque fois. J'ai créé ces méthodes pour tester le code sur des projets qui, pour une raison ou une autre, n'avait pas de moqueries paquet et je n'ai pas été invité à inclure.
Alors je peux tester la classe avec une variable privée de ce genre. Ceci est utile de se moquer de profondeur dans la classe des arbres que vous n'avez aucun contrôle ainsi.
J'ai modifié mon code de mon projet ici, dans la page. Il pourrait y avoir une compilation question ou deux. Je pense que vous avez l'idée générale. Hésitez pas à saisir le code et l'utiliser si vous le trouvez utile.
Beaucoup d'autres l'ont déjà conseillé vous de revoir votre code afin de le rendre plus testable - de bons conseils et généralement plus simple que ce que je suis sur le point de suggérer.
Si vous ne pouvez pas modifier le code afin de le rendre plus testable, PowerMock: https://code.google.com/p/powermock/
PowerMock s'étend Mockito (si vous n'avez pas à apprendre une nouvelle maquette cadre), fournissant des fonctionnalités supplémentaires. Cela inclut la possibilité d'avoir un constructeur de retour d'une fantaisie. Puissant, mais un peu compliqué donc l'utiliser à bon escient.
Vous utilisez un autre se Moquer de coureur. Et vous avez besoin pour préparer la classe qui va invoquer le constructeur. (Notez que ceci est une commune gotcha - préparer la classe qui appelle le constructeur, pas de la construction de la classe)
Puis dans votre essai, vous pouvez utiliser le whenNew méthode pour avoir le constructeur de retour d'un simulacre de
Oui, cela peut être fait, comme le test suivant montre (écrit avec le JMockit se moquant de l'API, que je développe):
Avec Mockito, cependant, qu'un tel test ne peut pas être écrit. Cela est dû à la façon dont se moquant est mis en œuvre dans Mockito, d'où une sous-classe de la classe se moque de lui est créé; les instances de cette "fantaisie" sous-classe peut avoir moqué de comportement, de sorte que vous besoin d'avoir le code à tester les utiliser à la place de toute autre instance.
Si vous voulez une alternative à ReflectionTestUtils de Printemps dans mockito, utilisez