150 votes

Comment résoudre l'exception de l'arrachage non nécessaire ?

Mon code est le suivant,

@RunWith(MockitoJUnitRunner.class)
public class MyClass {

    private static final String code ="Test";

    @Mock
     private MyClassDAO dao;

    @InjectMocks
     private MyClassService Service = new MyClassServiceImpl();

    @Test
     public void testDoSearch() throws Exception {
         final String METHOD_NAME = logger.getName().concat(".testDoSearchEcRcfInspections()");
         CriteriaDTO dto = new CriteriaDTO();
         dto.setCode(code);
         inspectionService.searchEcRcfInspections(dto);
         List<SearchCriteriaDTO> summaryList = new ArrayList<SearchCriteriaDTO>();
         inspectionsSummaryList.add(dto);
         when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
         verify(dao).doSearchInspections(dto);

      }
}

Je reçois l'exception suivante

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected in test class: Test
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.
  at org.mockito.internal.exceptions.Reporter.formatUnncessaryStubbingException(Reporter.java:838)
  at org.mockito.internal.junit.UnnecessaryStubbingsReporter.validateUnusedStubs(UnnecessaryStubbingsReporter.java:34)
  at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:49)
  at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:103)
  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Veuillez m'aider à résoudre ce problème

178voto

Dcortez Points 689

Vous devez d'abord vérifier votre logique de test. Il y a généralement 3 cas. Premièrement, vous vous trompez de méthode (vous avez fait une faute de frappe ou quelqu'un a modifié le code testé de sorte que la méthode simulée n'est plus utilisée). Deuxièmement, votre test échoue avant que cette méthode ne soit appelée. Troisièmement, votre logique tombe dans une mauvaise branche if/switch quelque part dans le code de sorte que la méthode simulée n'est pas appelée.

Si c'est le premier cas, vous devez toujours remplacer la méthode simulée par celle utilisée dans le code. Dans le deuxième et le troisième cas, cela dépend. Habituellement, vous devriez simplement supprimer cette méthode fantaisie si elle n'a pas d'utilité. Mais parfois il y a certains cas dans les tests paramétrés, qui devraient prendre ce chemin différent ou échouer plus tôt. Dans ce cas, vous pouvez diviser ce test en deux ou plusieurs tests distincts, mais ce n'est pas toujours bien vu. 3 méthodes de test avec éventuellement 3 fournisseurs d'arguments peuvent rendre votre test illisible. Dans ce cas, pour JUnit 4, vous supprimez cette exception avec soit

@RunWith(MockitoJUnitRunner.Silent.class) 

ou si vous utilisez l'approche par règle

@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);

ou (le même comportement)

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

Pour les tests JUnit 5, vous pouvez faire taire cette exception à l'aide de cette annotation fournie en mockito-junit-jupiter paquet :

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}

4 votes

@MockitoSettings(strictness = Strictness.LENIENT) est la façon la plus simple d'ajuster la rigueur dans ma configuration. Merci !

24 votes

Cette réponse donne un bon aperçu des possibilités. Toutefois, vous pouvez également définir la rigueur de l'indulgence au cas par cas en utilisant Mockito.lenient().when(...) pour cette question particulière, ce serait Mockito.lenient().when(dao.doSearch(dto)).thenReturn(inspect‌​ionsSummaryList);

0 votes

Définir ExtendWith dans la superclasse et MockitoSettings dans les sous-classes, lorsqu'il s'agit de hiérarchies de test. J'espère que cela fera gagner du temps à quelqu'un à mes frais.

135voto

Sumit Points 897

Remplacer @RunWith(MockitoJUnitRunner.class) con @RunWith(MockitoJUnitRunner.Silent.class) .

56 votes

Bienvenue. Cela vaudrait la peine de mettre à jour votre réponse pour expliquer por qué le PO doit remplacer ce code. Cela les aidera et aidera les futurs visiteurs à comprendre.

5 votes

En fait, c'est @RunWith(MockitoJUnitRunner.Silent.class) y pas SILENT

8 votes

En Kotlin : @RunWith(MockitoJUnitRunner.Silent::class)

63voto

philonous Points 839

Pour moi, ni le @Rule ni le @RunWith(MockitoJUnitRunner.Silent.class) Les suggestions ont fonctionné. Il s'agissait d'un ancien projet pour lequel nous avons effectué une mise à niveau vers mockito-core 2.23.0.

Nous pourrions nous débarrasser de la UnnecessaryStubbingException en utilisant :

Mockito.lenient().when(mockedService.getUserById(any())).thenReturn(new User());

au lieu de :

when(mockedService.getUserById(any())).thenReturn(new User());

Inutile de dire que vous devriez plutôt regarder le code de test, mais nous avions besoin de compiler le matériel et de faire fonctionner les tests avant tout ;)

14 votes

IMHO. C'est la réponse la plus utile que j'ai trouvée ici au lieu de faire taire toute la classe de test.

4 votes

Comme je voulais supprimer une seule moquerie, c'est la meilleure réponse pour moi. Mais ce n'est pas vraiment une réponse à l'OP.

0 votes

Je continue à obtenir le message Cannot resolve method 'lenient' dans 'Mockito'. Quelqu'un sait-il pourquoi ?

55voto

sgrillon Points 3641

Le silence n'est pas une solution. Vous devez corriger votre simulateur dans votre test. Voir la documentation officielle aquí .

Les stubs inutiles sont des appels de méthode stubés qui n'ont jamais été réalisés pendant l'exécution du test (voir aussi MockitoHint), exemple :

//code under test:
 ...
 String result = translator.translate("one")
 ...

 //test:
 ...
 when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
 when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
 ...

Remarquez que l'une des méthodes stubées n'a jamais été réalisée dans le code testé, pendant l'exécution du test. Le stubbing errant peut être un oubli du développeur, l'artefact d'un copier-coller ou l'effet d'une mauvaise compréhension du test/code. Dans tous les cas, le développeur se retrouve avec du code de test inutile. Afin de garder la base de code propre et maintenable, il est nécessaire de supprimer le code inutile. Sinon, les tests sont plus difficiles à lire et à comprendre.

Pour en savoir plus sur la détection des stubbings inutilisés, voir MockitoHint.

40 votes

Il existe de nombreuses situations où vous écrivez 8 à 9 tests avec une configuration @BeforeEach similaire et où l'élément renvoyé par un stub est inutilisé en raison de la logique commerciale d'une poignée de tests. Vous pouvez soit (A) le diviser en plusieurs tests et effectivement copier/coller la section @BeforeEach moins le seul élément (B) copier/coller la seule ligne pour laquelle Mockito est émotif dans les 6 tests qui l'utilisent et ne pas l'avoir dans les 2 qui ne l'utilisent pas ou (C) utiliser silent. Je préfère utiliser silent/warn. Ce n'est pas un test cassé.

1 votes

@RockMeetHardplace, Le silence n'est pas une solution En effet, on voit rapidement moins de copier/coller mais lors de la maintenance de vos tests par de nouvelles personnes sur votre projet, cela sera problématique. Si la librairie Mockito fait cela, ce n'est pas pour rien.

7 votes

@sgrillon : Mais ce système détecte beaucoup de faux-positifs. C'est à dire qu'il dit que quelque chose est inutilisé, mais ce n'est clairement pas le cas, car enlever le stub casse l'exécution. Ce n'est pas que le code de test ne peut pas être amélioré, c'est qu'une ligne vitale de stubbing devrait être enlevée. jamais être détecté comme "inutile". D'où l'importance de pouvoir désactiver cette vérification, elle est trop pressante.

29voto

john16384 Points 118
 when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
 verify(dao).doSearchInspections(dto);

El when configure ici votre objet fantaisie pour faire quelque chose. Cependant, vous n'utilisez plus cet objet fantaisie de quelque manière que ce soit après cette ligne (à part faire un verify ). Mockito vous avertit que le when est donc inutile. Peut-être avez-vous fait une erreur de logique ?

0 votes

Merci pour votre aide

0 votes

J'ai besoin des déclarations "quand" et "vérifie". Veuillez me suggérer comment aller plus loin.

2 votes

Appelez une fonction sur votre classe de test ( Service ) pour voir s'il réagit correctement. Vous ne l'avez pas fait du tout, alors que testez-vous ici ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X