À propos de l'article
Voici un autre guide de Mockito. Dans ce document, d'une part, j'ai essayé de décrire les fonctionnalités de cette bibliothèque afin qu'un lecteur qui ne la connaissait pas a immédiatement la possibilité de l'utiliser pleinement, et pas seulement une idée générale de celle-ci. D'un autre côté, je voulais le rendre suffisamment compact et structuré pour que je puisse le lire rapidement dans son intégralité et y trouver rapidement quelque chose une fois lu, mais oublié. En général, cet article, qui me serait utile moi-même, lorsque je suis tombé sur cette bibliothèque et que je ne comprenais pas vraiment comment cela fonctionne.
Je suppose que cela peut être utile pour moi maintenant - parfois j'oublie une partie de cela, et il est plus commode de rappeler le matériel non pas selon la documentation officielle ou les articles d'autres personnes, mais selon mon propre, disons, synopsis. En même temps, j'ai essayé de construire le texte de manière à ce qu'il soit pratique principalement pour explorer Mockito à partir de zéro, et à certains endroits, j'analyse en détail des choses apparemment évidentes - qui n'étaient pas toutes évidentes pour moi dès le début.
Contenu:
- Mockito: qu'est-ce que c'est et pourquoi est-il nécessaire
- Environnement, versions et animal expérimental
- moquer et espionner
- Gestion des comportements
- Définition des conditions d'appel
- Définition des résultats des appels
- Suivi des appels de méthode
- Mock objets en tant que valeurs de champ et annotations Mockito
- Comportement de restauration aux sessions par défaut et Mockito
- Quoi d'autre?
Mockito: qu'est-ce que c'est et pourquoi est-il nécessaire
En bref, Mockito est un framework stub.
Comme vous le savez, lors du test de code (principalement des tests unitaires, mais pas seulement), l'élément testé doit souvent fournir des instances de classes qu'il doit utiliser lors de son fonctionnement. Cependant, ils ne doivent souvent pas être pleinement fonctionnels - au contraire, ils doivent se comporter de manière strictement définie, de sorte que leur comportement soit simple et complètement prévisible. Ils sont appelés talons. Pour les obtenir, vous pouvez créer des implémentations de test alternatives d'interfaces, hériter des classes nécessaires avec redéfinition des fonctionnalités, etc., mais tout cela est assez gênant, redondant et semé d'erreurs. Une solution plus pratique dans tous les sens est des cadres spécialisés pour créer des talons. L'un d'entre eux (et peut-être le plus célèbre pour Java) est Mockito.
Mockito vous permet de créer avec une seule ligne de code le soi-disant faux (quelque chose comme la base du talon souhaité) de n'importe quelle classe. Pour une telle maquette, immédiatement après sa création, un certain comportement par défaut est caractéristique (toutes les méthodes renvoient des valeurs précédemment connues - généralement c'est null
ou 0
). Vous pouvez redéfinir ce comportement comme vous le souhaitez, le contrôler avec le bon degré de détail, etc. En conséquence, la maquette devient un talon avec les propriétés requises. Ci-dessous, je vais discuter en détail de la façon de procéder.
Je note que la simulation peut également être créée pour ces classes, dont la nouvelle instance ne peut pas simplement créer, en particulier, des classes avec des constructeurs exclusivement privés tels que les classes singleton et utilitaires, et avec une configuration minimale du cadre et des énumérations.
Environnement, versions et animal expérimental
Lors de la rédaction de cet article, j'ai utilisé:
- Mockito: 'org.mockito: mockito-core: 2.24.0' (dernière version stable au moment de la rédaction)
- TestNG: 'org.testng: testng: 6.14.3' comme cadre de test
- AssertJ: 'org.assertj: assertj-core: 3.11.1' comme outil de validation
- Lombok: 'org.projectlombok: lombok: 1.18.6' (juste pour plus de commodité)
- Java 8
Pour mes expériences inhumaines, j'ai écrit cette interface d'un service qui donne accès à certaines données.
public interface DataService { void saveData(List<String> dataToSave); String getDataById(String id); String getDataById(String id, Supplier<String> calculateIfAbsent); List<String> getData(); List<String> getDataListByIds(List<String> idList); List<String> getDataByRequest(DataSearchRequest request); }
Et ce code (que ce soit pour des raisons d'ordre) de la classe de demande est passé à la dernière des méthodes d'interface.
@AllArgsConstructor @Getter class DataSearchRequest { String id; Date updatedBefore; int length; }
Les unités de données sont identifiées par ID et ont quelques caractéristiques supplémentaires, mais directement sous la forme dans laquelle elles sont retournées par le service, ce sont des chaînes et non des objets plus complexes. Je ne manque rien d'important, et les exemples sont plus simples et plus clairs.
Je vais le noter tout de suite: dans les exemples ci-dessous, j'appelle directement les méthodes redéfinies de mes faux objets pour plus de clarté, mais avec de vrais tests, l'idée n'est pas du tout! Dans ce test, je ferais systématiquement ce qui suit:
- configuré la maquette de mon service au besoin;
- passé (très probablement, par le constructeur) à une instance d'une autre classe l'utilisant (supposons qu'il contient une sorte de logique métier utilisant les données fournies par le
DataService
), que je testerais en fait; - activé la fonctionnalité de la classe testée et contrôlé les résultats;
- si nécessaire, je contrôlerais le nombre et l'ordre des appels aux méthodes de ma maquette, qui auraient dû être appelées par la classe testée à la suite de l'action précédente.
moquer et espionner
La classe centrale de Mockito, à travers laquelle il est censé accéder à la plupart des fonctionnalités, est, en fait, une classe appelée Mockito
(il y a aussi la classe BDDMockito
qui offre à peu près les mêmes possibilités sous une forme plus adaptée au BDD , mais ici je ne m'y attarderai pas) . L'accès à la fonctionnalité est implémenté via ses méthodes statiques.
Pour créer une maquette de la classe DataService
, je dois juste faire ce qui suit:
DataService dataServiceMock = Mockito.mock(DataService.class);
Terminé - J'ai obtenu une instance de la classe dont j'ai besoin. Il sera accepté par n'importe quelle méthode ou constructeur qui nécessite un paramètre de ce type (par exemple, le constructeur de la classe que je veux tester). Même si un contrôle de dépendance l'attend plus tard, il le transmettra: non seulement instanceof DataService
renverra true
, mais aussi dataServiceMock.getClass()
- à savoir DataService.class
. D'une manière formelle, distinguer par programmation un objet simulé d'un objet ordinaire se révèle être une tâche plutôt difficile, ce qui est logique: après tout, le premier est destiné à être indiscernable du second. Cependant, Mockito a un outil pour cela - la méthode Mockito.mockingDetails
. En lui passant un objet arbitraire, j'obtiens un objet de la classe MockingDetails
. Il contient des informations sur ce que cet objet représente du point de vue de Mockito: qu'il s'agisse de maquette, d'espion (voir ci-dessous), comment il a été utilisé, comment il a été créé, etc.
Il convient de noter en particulier la situation lorsque j'essaie de créer un mock pour la classe finale ou une instance fictive d'énumération ou de remplacer le comportement de la méthode finale. Dans ce cas, avec le comportement par défaut de Mockito, le code ci-dessus refuse de fonctionner, citant précisément cette circonstance. Cependant, cela peut être changé - il suffit de créer dans le projet (avec le périphérique standard de l'arborescence du répertoire du projet) le fichier test/resources/mockito-extensions/org.mockito.plugins.MockMaker
et entrez la ligne dedans:
mock-maker-inline
Après cela, vous pouvez imiter les classes et énumérations finales de la manière habituelle, ainsi que remplacer les méthodes finales.
La maquette que j'ai eue en action est aussi impropre que possible: pas une seule méthode n'aura d'effet sur quoi que ce soit, et la valeur retournée sera null
pour les types d'objets et 0
pour les types primitifs. Remarque: si la méthode retourne une collection, la maquette par défaut ne renverra pas les null
, mais les instances de collection vides. Par exemple, pour List
cela se révélera être une LinkedList
vide LinkedList
indépendamment de ce que la vraie méthode aurait dû retourner. Mais comme les valeurs des tableaux, primitifs ou objet, j'obtiens null
. Le comportement par défaut (et pas seulement) peut être modifié à l'aide des fonctionnalités de la classe MockSettings
, mais cela est rarement nécessaire.
D'une manière ou d'une autre, dans la plupart des cas, je n'aurai pas besoin du comportement par défaut, et dans la section suivante, j'analyserai en détail comment définir ce qui est requis à la place.
Cependant, que se passe-t-il si je souhaite utiliser un objet de classe réel avec les fonctionnalités disponibles en tant que stub, redéfinissant le fonctionnement d'une partie seulement de ses méthodes? Si nous parlons de tests unitaires, un tel besoin indique généralement (mais pas toujours) que le projet ne convient pas à la conception et, en principe, ce n'est pas recommandé. Cependant, il existe des situations où cela, pour une raison quelconque, ne peut être évité. Pour ce cas, Mockito a le soi-disant espion, "espions". Contrairement aux maquettes, ils peuvent être créés en fonction de la classe et de l'objet fini:
DataService dataServiceSpy = Mockito.spy(DataService.class);
Lors de la création d'un espion basé sur une classe, si son type est une interface, un objet maquette normal sera créé, et si le type est une classe, alors Mockito essaiera de créer une instance en utilisant le constructeur par défaut (sans paramètres). Et seulement s'il n'y a pas un tel constructeur, une erreur se produira et le test ne fonctionnera pas.
Le comportement des objets espions par défaut est identique au comportement d'une instance de classe régulière, mais ils me donnent les mêmes possibilités que les objets fictifs: ils me permettent de redéfinir leur comportement et de surveiller leur utilisation (voir les sections suivantes). Un point important: spy n'est pas un wrapper autour de l'instance sur laquelle il a été créé! Par conséquent, l'appel de la méthode spy n'affectera pas l'état de l'instance d'origine.
Gestion des comportements
Donc, sur la façon de se moquer ou d'espionner pour faire ce dont j'ai besoin. De plus, j'écrirai toujours simplement «simulacre» partout - cela signifiera «simulacre ou espion», sauf indication contraire expresse.
En général, le contrôle du comportement d'un objet simulé se résume à un concept évident: quand une maquette a été traitée de cette manière (c'est-à-dire qu'une méthode avec tel ou tel argument a été appelée), elle devrait répondre de telle ou telle manière. Ce concept a deux implémentations au sein de la classe Mockito - la principale, recommandée par les développeurs pour une utilisation dans la mesure du possible, et l'autre, utilisée lorsque la principale ne convient pas.
L'implémentation principale est basée sur la méthode Mockito.when
. Cette méthode prend comme «paramètre» un appel à la méthode redéfinie de l'objet maquette (de cette façon l'action détectée est fixée) et retourne un objet de type OngoingStubbing
, qui permet d'appeler l'une des méthodes de la famille Mockito.then...
(c'est ainsi que la réaction à cet effet est définie). Dans l'ensemble, dans le cas le plus simple, cela ressemble à ceci:
List<String> data = new ArrayList<>(); data.add("dataItem"); Mockito.when(dataService.getAllData()).thenReturn(data);
Après cette opération, en appelant la méthode getAllData()
sur l'objet getAllData()
, j'obtiens l'objet spécifié dans la première ligne de la liste.
Ici, l'intuition familière "orientée objet" peut donner une sorte de dysfonctionnement, donc cela mérite d'être approfondi. Du point de vue de la syntaxe Java, la valeur transmise à la méthode when
tant que paramètre est, bien sûr, la valeur renvoyée par la méthode substituée. Pour mock, c'est une valeur vide; pour spy, c'est la valeur retournée par la méthode de l'objet réel. Mais grâce à l'action magique «sous le capot» de Mockito, la méthode when
ne fonctionnera normalement (et ne plantera pas lorsqu'elle sera lancée avec une erreur) que si l'appel de la méthode mock-object est entre crochets après when
.
Une idéologie similaire fonctionne souvent lors de la définition du comportement d'un mockito dans un Mockito: en appelant une méthode (d'un objet Mockito
ou d'une classe du Mockito
), j'essaie de ne pas obtenir la valeur retournée par celui-ci, mais en quelque sorte d'influencer l'appel possible de la méthode de l'objet Mockito
je travaille: spécifier ses limites, fixer le résultat, établir l'observation de ses défis, etc. Cela semble un peu brumeux, je l'avoue, et à la première collision, cela semble étrange, mais, après l'avoir compris, vous commencez bientôt à ressentir cette approche comme tout à fait naturelle dans le contexte du travail avec des talons.
Une autre implémentation de la liaison de la condition et du résultat de l'appel est les méthodes de la famille Mockito.do...
Ces méthodes vous permettent de définir le comportement en commençant par le résultat de l'appel et de renvoyer un objet de la classe Stubber
, avec lequel vous pouvez déjà définir la condition. La même liaison que ci-dessus effectuée de cette manière ressemble à ceci:
List<String> data = new ArrayList<>(); data.add("dataItem"); Mockito.doReturn(data).when(dataService).getData()
Quelle est la différence, pourquoi la liaison via Mockito.when
est considérée comme préférable et quand vous devez encore utiliser les méthodes de Mockito.do...
? Remarque: dans la première implémentation, lors de la définition du comportement de la méthode (dans ce cas, getAllData()
), l'appel à la version qui n'a pas encore été redéfinie est effectué en premier, puis seulement, dans les entrailles de Mockito, un remplacement se produit. Dans le second cas, un tel appel ne se produit pas - la méthode Stubber.when
passée directement à la méthode Stubber.when
, et un objet du même type, mais de nature différente, est renvoyé à partir de la méthode renvoyée par cette méthode. Cette différence détermine tout. La liaison via Mockito.do...
ne contrôle pas au moment de la compilation quelle méthode redéfinissable j'appellerai et si elle est compatible avec le type avec la valeur de retour donnée. Par conséquent, généralement Mockito.when
préférable - il ne peut y avoir aucune erreur avec cela. Mais il peut y avoir des cas où je veux éviter d'appeler une méthode redéfinie - pour une maquette nouvellement créée, un tel appel est tout à fait acceptable, mais si j'ai déjà redéfini cette méthode ou traité avec un espion, cela peut être indésirable, et lever une exception ne permettra pas du tout la redéfinition nécessaire . Et ici, la liaison via Mockito.do...
vient à la Mockito.do...
Une autre situation où vous ne pouvez pas vous passer des méthodes Mockito.do...
est la Mockito.do...
la méthode renvoyant void
: le paramètre Mockito.when
attente ne peut pas fonctionner avec une telle méthode. Mockito.doReturn
, bien sûr, sans travail, mais il y a Mockito.doThrow
, Mockito.doAnswer
et rarement assez Mockito.doNothing
.
Ensuite, je considérerai un peu plus en détail comment définir les conditions et les résultats des appels. Je ne considérerai que la liaison via Mockito.when
- une autre méthode est presque complètement similaire dans la manipulation.
Définition des conditions d'appel
L'exemple ci-dessus concerne une méthode sans paramètres, et la condition d'appel associée est possible une chose - le fait de l'appel. Dès que les paramètres apparaissent, la situation devient plus compliquée. Au minimum, pour appeler une méthode dont je définis le comportement, je dois lui passer quelque chose. Mais une autre chose est plus importante: il peut s'avérer que je ne veux pas toujours obtenir la réaction donnée, mais seulement lorsque je l'appelle avec des paramètres qui répondent à certaines exigences. DataService
a cette méthode:
String getDataItemById(String id) {
Si je dois définir une réponse à tout appel à cette méthode, quels que soient les arguments, je dois utiliser la méthode Mockito.any
:
Mockito.when(dataService.getDataItemById(any())) .thenReturn("dataItem");
Si je veux que mock ne réponde qu'à une certaine valeur de l'argument, vous pouvez utiliser cette valeur directement ou les méthodes de Mockito.eq
(si nous parlons d'équivalence) ou Mockito.same
(si une comparaison de liens est requise):
Mockito.when(dataService.getDataItemById("idValue")) .thenReturn("dataItem");
Et si je veux que l'argument réponde à certaines exigences, il existe un certain nombre de méthodes statiques spécialisées pratiques de la même classe Mockito
(par exemple, les chaînes peuvent être vérifiées pour le contenu au début ou à la fin d'une certaine séquence de caractères, la correspondance de modèle, etc.). Il existe également une méthode générale Mockito.argThat (et ses analogues pour les types primitifs) qui accepte l'implémentation de l'interface fonctionnelle ArgumentMatcher:
Mockito.when(dataService.getDataById( Mockito.argThat(arg -> arg == null || arg.length() > 5))) .thenReturn("dataItem");
Les classes ArgumentMatchers
et AdditionalMatchers
vous permettent de travailler avec certaines implémentations prêtes à l'emploi de cette interface. Par exemple, AdditionalMatchers.or
et AdditionalMatchers.and
vous permettent de combiner d'autres matchers (remarque: les méthodes statiques de ces classes ne renvoient pas d'instances de matchers, mais y accèdent uniquement!)
Pour la même méthode, vous pouvez définir le comportement plusieurs fois avec des exigences différentes pour les arguments, et tous les modèles de comportement définis de cette manière agiront simultanément. Bien sûr, dans certains cas, ils peuvent se croiser - disons, je demanderai de retourner un résultat lorsque la valeur int
du paramètre est inférieure à 5 et l'autre lorsque la valeur paire est reçue. Dans ce cas, le comportement spécifié ultérieurement a priorité. Par conséquent, lors de la définition de modèles de comportement complexes, vous devez commencer par les exigences les plus faibles (dans la limite - any()
) et ensuite passer à des exigences plus spécifiques.
Lorsque vous travaillez avec des méthodes avec plusieurs arguments, les exigences spécifiées sont combinées conformément au ET logique, c'est-à-dire que pour obtenir le résultat spécifié, CHAQUE des arguments doit répondre à l'exigence indiquée. Je n'ai pas trouvé de moyen de définir une manière arbitraire de les combiner, bien qu'il existe peut-être.
De plus, lors de la spécification du comportement d'une telle méthode, on ne peut pas combiner les méthodes statiques de Mockito
et le transfert direct de valeurs. Utilisez Mockito.eq
ou Mockito.same
.
Définition des résultats des appels
Après l'appel de la méthode de l'objet factice, l'objet doit répondre à l'appel. Les principales conséquences possibles sont le retour du résultat et la levée d'une exception, et c'est précisément sur ces options que la boîte à outils Mockito est principalement conçue.
Dans le cas le plus simple déjà montré ci-dessus, la réponse à l'appel est de renvoyer une valeur. Je vais redonner son code:
List<String> data = new ArrayList<>(); data.add("dataItem"); Mockito.when(dataService.getAllData()).thenReturn(data);
Remarque: vous ne pouvez renvoyer qu'un objet; il n'y a pas de méthodes distinctes pour les primitives. Par conséquent, si la méthode renvoie une valeur primitive, dans une telle situation, un / boxing se produira. Dans la plupart des cas, cela n'interfère pas, mais si le compilateur pense le contraire, vous devrez en quelque sorte être d'accord avec lui ... ou accepter ses avertissements.
Lancer des exceptions n'est pas plus difficile:
Mockito.when(dataService.getDataById("invalidId")) .thenThrow(new IllegalArgumentException());
Il existe un autre moyen: vous pouvez créer un objet d'exception et le lancer directement, ou vous pouvez fournir à Mockito uniquement une classe d'exception afin qu'il soit créé automatiquement:
Mockito.when(dataService.getDataById("invalidId")) .thenThrow(IllegalArgumentException.class);
Dans les deux cas, la syntaxe vous permet d'utiliser et de vérifier les exceptions, cependant, Mockito ne vous permettra pas d'exécuter un tel test si le type d'exception ne correspond pas à la méthode que je souhaite forcer à lever cette exception.
Lorsque vous utilisez une classe comme paramètre, les constructeurs (même sans paramètres), ainsi que l'initialisation directe des champs, sont ignorés - l'objet est créé en les contournant (après tout, c'est Mockito!), De sorte que tous les champs de l'exception levée seront null
. Par conséquent, si le contenu de l'exception vous intéresse (par exemple, un champ de type
qui a une valeur par défaut), vous devrez abandonner cette méthode et créer des exceptions manuellement.
Ces options de réaction conviennent si, en réponse à un appel avec des conditions données, vous devez toujours renvoyer une certaine valeur, toujours la même valeur du résultat ou toujours lever la même exception, et dans la plupart des cas, ces capacités sont tout à fait suffisantes. Mais que se passe-t-il si davantage de flexibilité est requise? Supposons que ma méthode accepte une collection de valeurs et renvoie une autre collection de valeurs associée à la première à une (par exemple, obtenir une collection d'objets de données par l'ensemble de leurs ID), et que je souhaite utiliser cet objet simulé à plusieurs reprises avec différents ensembles d'entrée dans le test données, obtenant à chaque fois le résultat correspondant. Vous pouvez, bien sûr, décrire séparément la réaction à chaque ensemble spécifique de paramètres, mais il existe une solution plus pratique - la méthode Mockito.thenAnswer
, alias Mockito.then
. Il accepte une implémentation de l'interface fonctionnelle Answer
, dont la seule méthode est de recevoir un objet de la classe InvocationOnMock
. À partir de ce dernier, je peux demander les paramètres de l'appel de méthode (un par un ou tous à la fois sous forme de tableau) et agir avec eux, à ma guise. Par exemple, vous pouvez obtenir une valeur qui lui correspond pour chacun des éléments de ma collection, en former une nouvelle collection et la renvoyer (remarque: le résultat souhaité est simplement renvoyé, mais pas écrit dans un champ de l'objet paramètre, comme vous pouvez vous y attendre):
Mockito.when(dataService.getDataByIds(Mockito.any())) .thenAnswer(invocation -> invocation .<List<String>>getArgument(0).stream() .map(id -> { switch (id) { case "a": return "dataItemA"; case "b": return "dataItemB"; default: return null; } }) .collect(Collectors.toList()));
Idéologiquement, cela revient à écrire un modèle de méthode réelle: obtenir des paramètres, traiter, retourner un résultat. - , - , , , mock- .
Answer
, , — , AnswersWithDelay
, ReturnsElementsOf
. .
: InvocationOnMock
— Object[]
, generic-.
— thenCallRealMethod
. . mock-, spy-. mock , , - null
. spy thenCallRealMethod
spy ; , - .
thenAnswer
: InvocationOnMock
callRealMethod()
— , "" - .
OngoingStubbing
OngoingStubbing
, , , . , . thenReturn
thenThrow
, varargs. .
Mockito.when(dataService.getDataById("a")) .thenReturn("valueA1", "valueA2") .thenThrow(IllegalArgumentException.class);
"valueA1
, — "valueA2
( ), ( ) IllegalArgumentException
.
: (mock' ), . , : , , . verify
.
, , :
Mockito.verify(dataService).getDataById(Mockito.any());
, getDataById
, , . , Mockito, when
, , , mock-. , , , when
, — mock', (. ).
:
Mockito.verify(dataService, Mockito.times(1)) .getDataById(Mockito.any());
Mockito.times
; Mockito.never
. Mockito.atLeast
( Mockito.atLeastOnce
1) Mockito.atMost
, , Mockito.only
, , mock- (. . ).
, Mockito
, VerificationAfterDelay
VerificationWithTimeout
, Mockito.after
Mockito.timeout
. Par exemple:
Mockito.verify(dataService, Mockito.after(1000).times(1)) .getDataById(Mockito.any());
, mock , , , . . after
timeout
, , , — , . , timeout
— . VerificationWithTimeout
never
atMost
: .
, Mockito.any()
. , , — Mockito , , . Mock- , , , , :
dataService.getDataById("a"); dataService.getDataById("b"); Mockito.verify(dataService, Mockito.times(2)).getDataById(Mockito.any()); Mockito.verify(dataService, Mockito.times(1)).getDataById("a"); Mockito.verify(dataService, Mockito.never()).getDataById("c"); dataService.getDataById("c"); Mockito.verify(dataService, Mockito.times(1)).getDataById("c"); Mockito.verifyNoMoreInteractions(dataService);
verifyNoMoreInteractions
( verifyZeroInteractions
) — - ( verify
) mock- — . : varargs, , , !
, , , . , InOrder
:
InOrder inOrder = Mockito.inOrder(dataService);
varargs; — mock- , InOrder
. verify
, Mockito.verify
:
inOrder.verify(dataService, times(2)).saveData(any()); inOrder.verify(dataService).getData();
, saveData
, — getData
. , InOrder
, — .
, , — , . - , , — , , . ArgumentCaptor
capture()
. Par exemple:
DataSearchRequest request = new DataSearchRequest("idValue", new Date(System.currentTimeMillis()), 50); dataService.getDataByRequest(request); ArgumentCaptor<DataSearchRequest> requestCaptor = ArgumentCaptor.forClass(DataSearchRequest.class); Mockito.verify(dataService, times(1)).getDataByRequest(requestCaptor.capture()); assertThat(requestCaptor.getAllValues()).hasSize(1); DataSearchRequest capturedArgument = requestCaptor.getValue(); assertThat(capturedArgument.getId()).isNotNull(); assertThat(capturedArgument.getId()).isEqualTo("idValue"); assertThat(capturedArgument.getUpdatedBefore()).isAfterYear(1970); assertThat(capturedArgument.getLength()).isBetween(0, 100);
ArgumentCaptor
, , ArgumentCaptor
. getValue()
, getAllValues()
— . , , .
Mock- Mockito
, mock- , — @Mock
- :
MockitoAnnotations.initMocks(this);
( , mock', )
spy @Spy
— @Mock
… spy , , ? , — spy .
@Captor
ArgumentCaptor
— , , .
@InjectMocks
. - Mockito, . mock- , . , . - , null
, - . ( ) dependency injection.
Mockito
, : mock (spy, argument captor...), , , . , mock' — , . JUnit , , TestNG — . , , mock' , , , . . , , — , .
, mock- . TestNG @BeforeMethod
( @AfterMethod
). mock' , , ( JUnit — @Before
).
, , — Mockito.reset
Mockito.clearInvocations
. varargs, mock'. , . : (, ) , / mock' , — . , mock' . . , , .
(, ) — MockitoAnnotations.initMocks(this);
. "" , Mockito.
— Mockito. . mock- , ( mock' ). , MockitoSession
, . TestNG:
@Mock DataService dataService; MockitoSession session; @BeforeMethod public void beforeMethod() { session = Mockito.mockitoSession() .initMocks(this) .startMocking(); } @Test public void testMethod() {
, — , "" (, ) , .
?
Mockito: mock spy-, . , . , , :
- Mockito mock-
MockSettings
( — , mock' - ); - mock-,
MockingDetails
; BDDMockito
Mockito
;- ( JUnit Mockito, ).
Mockito . javadoc' Mockito
.
, , .