[JAVA] Comment écrire Mockito

Puisque la page qui présente la méthode de description de Mockito lors des tests avec JUnit + Mockito est appropriée, je l'ai organisée à ma manière.

environnement

Caractéristiques de Mockito

Mock

Il est utilisé lorsque vous souhaitez simuler et remplacer toutes les méthodes de l'instance cible. Dans l'état par défaut, pour les objets, les méthodes avec une valeur de retour renverront null. (Dans Collection, c'est une Collection vide, et dans les valeurs primitives, c'est 0 ou faux ...)

Il peut être simulé en ajoutant l'annotation @ Mock. De plus, en affectant @ InjectMocks à l'instance de la classe à tester, Vous pouvez brancher une instance fictive de «@ Mock» dans une instance d'un membre «@ Inject» dans une instance.

Spy

Utilisez cette option lorsque vous souhaitez remplacer uniquement une méthode spécifique de l'instance cible. Je ne suis pas très doué pour ça. Y a-t-il un cas où vous souhaitez utiliser le getter et d'autres méthodes telles quelles et remplacer une seule méthode?

Il peut être utilisé en ajoutant l'annotation @ Spy. Vous devez créer l'instance vous-même. Il ne peut pas être injecté avec @ InjectMocks.

Captor

Principalement utilisé pour capturer et valider les valeurs des arguments. Si l'argument est un objet, il ne peut pas être vérifié avec un matcher standard tel que ʻeq`. À ce moment, Captor est efficace.

Lors de la capture d'arguments, définissez une instance de la classe ArgumentCaptor et donnez-lui @ Captor.

Comment rédiger un test de base

En supposant que vous concevez en utilisant DI, nous résumerons la description de base en utilisant Mockito.

Politique de base

--Réglez le mode de Mockito sur Strict Stubs. --Mockito a trois modes: Silent, Strict (v2 par défaut) et StrictStubs. --Si vous le définissez sur StrictStubs, il détectera également la discordance d'arguments du simulacre qui devient le stub, alors définissez-le sur le plus strict.

Et cela. ――Personnellement, il est difficile d'apprendre la méthode de description une par une en fonction de la présence ou de l'absence de la valeur de retour et de la différence entre Mock et Spy. Je pense que ce sera compliqué à regarder.

Préparation

  1. Donnez-le à la classe de test @RunWith (MockitoJUnitRunner.StrictStubs.class), ce qui est magique d'utiliser Mockito dans le test.
  1. Ajoutez @ InjectMocks à la variable de la classe à tester.
  2. Ajoutez @ Mock à la variable de la classe que vous voulez moquer. -Ajoutez simplement les annotations @InjectMocks et @Mock pour créer une instance.
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
...

@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class XXTest{
  @InjectMocks
  XXInteractor target;

  @Mock
  IXXRepository repoMock;

  ...
}

cas de test

  1. Définissez une méthode publique vide avec @ Test.
  2. Décrivez la définition de la méthode pour laquelle vous souhaitez simuler l'instance fictive.
  3. Appelez la méthode testée.
  4. Vérifiez le résultat.

Lorsque la cible du test est la suivante

public class XXInteractor{
  @Inject
  IXXRepository repository;

  XXEntity fetch(String id) throws NotFoundException{
    try{
      return repository.findBy(id);
    }
    catch(UseCaseNotFoundException e){
      throw new NotFoundException();
    }
  }
}

Vous pouvez écrire le test suivant.

  private static final String ID = "ID";

  @Test
  public void testFetchSuccess() throws Exception{
    //Renvoie une XXEntity normale uniquement lorsqu'un ID est donné en argument.(Sinon, nul)
    doReturn(new XXEntity(ID))
      .when(repoMock).findBy(eq(ID));

    XXEntity result = target.fetch(ID);

    assertThat(result.getId(), is(ID));
  }

  @Test(expected = NotFoundException.class)
  public void testFetchFailureWithNotFound() throws Exception{
    doThrow(new RepositoryNotFoundException())
      .when(repoMock).findBy(eq(ID));

    target.fetch(ID);
  }

Cas d'utilisation simulé

Édition de base

Le modèle de moquerie de base est illustré ci-dessous.

Renvoie une valeur avec une méthode simulée

//S'il y a une valeur de retour
doReturn(new XXEntity(ID))
  .when(targetMock).fetch(eq(ID));

//S'il n'y a pas de valeur de retour
doNothing().when(targetMock).delete(eq(ID))

Lever une exception dans une méthode simulée

doThrow(new XXException()).when(targetMock).fetch(eq(ID))

doThrow(new XXException()).when(targetMock).delete(eq(ID))

Remplacez la méthode de l'instance Spy

//Renvoie la valeur de retour
doReturn(new XXEntity()).when(targetSpy).fetch()

//Lever une exception
doThrow(new XXException()).when(targetSpy).fetch()

Version avancée

Je veux répondre si un argument est appelé

doReturn(new XXEntity(ID))
  .when(targetMock).fetch(any())

Je souhaite renvoyer une valeur différente pour chaque appel avec la même méthode

//Cas sans arguments, ou cas où vous souhaitez renvoyer une valeur différente pour chaque appel avec les mêmes arguments
//Ce cas ne peut pas être écrit avec doReturn, alors décrivez-le au format thenReturn.
when(targetMock.getNextKey())
  .thenReturn("ID-1")   //Premier appel
  .thenReturn("ID-2");  //Deuxième appel

//Cas qui renvoient des valeurs différentes pour chaque argument(Définissez chacun normalement)
doReturn(new XXEntity("ID-1")).when(targetMock).fetch(eq("ID-1");
doReturn(new XXEntity("ID-2")).when(targetMock).fetch(eq("ID-2");

Je veux valider des arguments non primitifs

Si l'argument est primitif, il ne peut être vérifié qu'avec ʻeq`, mais si l'argument est un objet ou un système de carte de liste, il ne peut pas être vérifié, il doit donc être combiné avec Captor.

Lorsque la cible du test est la suivante

public class XXInteractor{
  @Inject
  IXXRepository repository;

  void update(XXEntity entity){
    repository.update(entity);
  }
}

Vérifiez comme suit.

  private static final String ID = "ID";

  @InjectMocks
  XXUseCase target;

  @Mock
  IXXRepository repoMock;

  //Définir le capteur
  @Captor
  ArgumentCaptor<XXEntity> argCaptor;

  @Test
  public void testUpdateSuccess(){
    //Définir une maquette pour capturer les arguments
    doNothing().when(repoMock).update(argCaptor.capture());

    target.update(ID);

    //Valider les arguments capturés
    assertThat(argCaptor.getValue().getId(), is(ID));
  }

Je veux réécrire les arguments qui sont venus au simulacre

Un cas de moquerie d'une méthode qui implémente quelque chose comme ref en C # qui utilise une partie de l'argument comme valeur de retour. Cette définition de méthode n'est pas testable, elle doit donc être essentiellement résolue par une modification de conception, Si vous voulez vraiment réécrire le contenu de l'instance que vous avez reçue en argument, vous pouvez le faire par la méthode suivante.

doAnswer( invocation -> {
  Object[] args = invocation.getArguments();

  //En convertissant l'argument dans cette classe, vous pouvez manipuler cette instance.
  //Dans ce cas, le deuxième argument est réécrit, donc args[1]
  ((XXOutputParam) args[1]).setId("ID");
  return null; //Null si la valeur de retour est nulle
}).when(useCaseMock).get(any(), any())

Je veux réinitialiser le mouvement de la maquette

Appelez-le à chaque fois avec la méthode @ Before.

reset(mock);

référence

https://static.javadoc.io/org.mockito/mockito-core/2.23.4/org/mockito/Mockito.html

Recommended Posts

Comment écrire Mockito
Comment écrire des rails
Comment écrire docker-compose
Comment écrire un fichier de migration
Comment écrire du bon code
Comment rédiger un commentaire java
[Refactoring] Comment écrire le routage
Comment écrire Junit 5 organisé
Comment écrire des graines de Rails
Comment écrire le routage Rails
Étudier Java # 6 (Comment écrire des blocs)
[Rails] Comment écrire la gestion des exceptions?
Comment écrire une déclaration de variable Java
Comment rédiger un code facile à comprendre [Résumé 3]
[Basique] Comment écrire un auto-apprentissage Dockerfile ②
Résumé de l'écriture des arguments d'annotation
[Introduction à Java] Comment écrire un programme Java
[Java] Comment sortir et écrire des fichiers!
Comment écrire un spécificateur de coupe de point Spring AOP
[SpringBoot] Comment écrire un test de contrôleur
Promesse JDBC et exemple d'écriture
Comment se moquer de chaque cas avec Mockito 1x
Comment développer OpenSPIFe
[Java FX] Comment écrire des autorisations Eclipse dans build.gradle
Comment rédiger la réponse à la 15e question de référence hors ligne
Comment appeler AmazonSQSAsync
Comment utiliser Map
Bases du développement Java ~ Comment écrire des programmes * Exercice 1 ~
Comment utiliser with_option
Comment utiliser fields_for
Comment utiliser java.util.logging
Comment utiliser la carte
Comment utiliser collection_select
JUnit 5: Comment écrire des cas de test dans enum
Comment utiliser Twitter4J
Comment utiliser active_hash! !!
Comment installer Docker
Comment utiliser MapStruct
Comment utiliser TreeSet
Comment désinstaller Rails
Comment installer docker-machine
[Comment utiliser l'étiquette]
Comment faire un pot ombré
Comment utiliser le hachage
Exemple d'implémentation de F06 d'écriture en temps réel hors ligne
Comment écrire du code qui pense Ruby orienté objet