web-dev-qa-db-fra.com

@RunWith (MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks (this)

En écrivant un nouveau test jUnit4, je me demande s’il faut utiliser @ RunWith (MockitoJUnitRunner.class) ou MockitoAnnotations.initMocks (this).

J'ai créé un nouveau test et l'assistant a automatiquement généré un test avec le Runner. Les Javadocs pour MockitoJUnitRunner indiquent ce qui suit:

Compatible avec JUnit 4.4 et supérieur, ce coureur ajoute le comportement suivant:

Initialise les mockings annotés avec Mock, de sorte que l'utilisation explicite de MockitoAnnotations.initMocks (Object) ne soit pas nécessaire. Les échantillons sont initialisés avant chaque méthode de test. valide l'utilisation de la structure après chaque méthode de test.

Il n'est pas clair pour moi si l'utilisation du Runner a un avantage sur la méthode initMocks () que j'utilisais dans le passé.

Toutes les pensées ou les liens seraient appréciés!

95
OceanBlue

MockitoJUnitRunner vous donne une validation automatique de l'utilisation du framework, ainsi qu'une initMocks() automatique.

La validation automatique de l’utilisation du framework est réellement utile. Cela vous donne de meilleurs rapports si vous commettez l'une de ces erreurs.

  • Vous appelez la méthode statique when, mais ne complétez pas le stubbing avec une correspondance thenReturn, thenThrow ou then. (Erreur 1 dans le code ci-dessous)

  • Vous appelez verify sur une maquette, mais vous oubliez de fournir l'appel de méthode que vous essayez de vérifier. (Erreur 2 dans le code ci-dessous)

  • Vous appelez la méthode when après doReturn, doThrow ou doAnswer et transmettez une simulation, mais oubliez de fournir la méthode que vous essayez de remplacer. (Erreur 3 dans le code ci-dessous)

Si vous ne possédez pas de validation de l'utilisation de la structure, ces erreurs ne sont pas signalées avant l'appel suivant à une méthode Mockito. Cela pourrait être

  • dans la même méthode de test (comme l'erreur 1 ci-dessous),
  • dans la méthode de test suivante (comme l'erreur 2 ci-dessous),
  • dans la prochaine classe de test.

S'ils se produisent dans le dernier test que vous avez exécuté (comme l'erreur 3 ci-dessous), ils ne seront pas signalés du tout.

Voici à quoi pourrait ressembler chacun de ces types d’erreurs. Supposons ici que JUnit exécute ces tests dans l'ordre indiqué.

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called.
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen.
    when(myMock.method1());

    doSomeTestingStuff();

    // ERROR 1 is reported on the following line, even though it's not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call to verify.  But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error.
    doReturn("Hello").when(myMock).method1();


    // ERROR 3
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call is being stubbed.  But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen.

    doReturn("World").when(myMock);

    doSomeTestingStuff(); 

    //  ERROR 3 is never reported, because there are no more Mockito calls. 
}

Maintenant, quand j'ai écrit cette réponse pour la première fois il y a plus de cinq ans, j'ai écrit

Je recommanderais donc l’utilisation du MockitoJUnitRunner dans la mesure du possible. Cependant, comme l'a correctement souligné Tomasz Nurkiewicz, vous ne pouvez pas l'utiliser si vous avez besoin d'un autre coureur JUnit, tel que celui de Spring.

Ma recommandation a maintenant changé. L'équipe Mockito a ajouté une nouvelle fonctionnalité depuis que j'ai écrit cette réponse pour la première fois. C'est une règle JUnit, qui remplit exactement la même fonction que MockitoJUnitRunner. Mais c'est mieux, car cela n'empêche pas l'utilisation d'autres coureurs.

Comprendre

@Rule 
public MockitoRule rule = MockitoJUnit.rule();

dans votre classe de test. Cela initialise les simulacres et automatise la validation de la structure; comme MockitoJUnitRunner le fait. Mais maintenant, vous pouvez utiliser SpringJUnit4ClassRunner ou tout autre JUnitRunner également. À partir de Mockito 2.1.0, des options supplémentaires permettent de contrôler exactement le type de problème signalé.

119

Utiliser Runner vous permet d’économiser un peu de code (pas besoin de @Before méthode). Par contre, utiliser un coureur n’est parfois pas possible, c’est-à-dire lorsque vous en utilisez déjà un, comme SpringJUnit4ClassRunner .

C'est ça. C'est juste une question de préférence.

23