web-dev-qa-db-fra.com

Comment résoudre une exception Stubbing Unneccessary

Mon code est comme ci-dessous, 

@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 en dessous de l'exception

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)

S'il vous plaît aidez-moi comment résoudre

46
VHS

Remplacez @RunWith(MockitoJUnitRunner.class) par @RunWith(MockitoJUnitRunner.Silent.class).

81
Sumit

Au début, vous devriez vérifier votre logique de test. Il y a généralement 3 cas. Tout d'abord, vous vous moquez de la mauvaise méthode (vous avez créé 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 le faux si/change de branche quelque part dans le code, de sorte que la méthode fausse n’est pas appelée.

Si c'est le premier cas, vous voulez toujours changer la méthode fausse pour celle utilisée dans le code. Avec le deuxième et le troisième cela dépend. Habituellement, vous devriez simplement supprimer cette maquette si elle n’a aucune utilité. Mais il arrive parfois que des tests paramétrés présentent certains cas, qui doivent suivre ce chemin différent ou échouer plus tôt. Ensuite, vous pouvez diviser ce test en deux ou plusieurs tests distincts, mais ce n’est pas toujours beau. 3 méthodes de test avec éventuellement 3 arguments fournisseurs peuvent vous rendre test illisible. Dans ce cas, pour JUnit 4, cette exception a été masquée soit avec 

@RunWith(MockitoJUnitRunner.Silent.class) 

annotation 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 désactiver cette exception en utilisant l'annotation fournie dans le package mockito-junit-jupiter.

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}
26
Dcortez
 when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
 verify(dao).doSearchInspections(dto);

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

16
john16384

Le silence n'est pas une solution. Vous devez réparer votre maquette lors de votre test. Voir la documentation officielle ici.

Les stubs inutiles sont des appels de méthode stubbed 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
 ...

Notez que l’une des méthodes stubbed n’a jamais été réalisée dans le code sous test, lors de l’exécution du test. Le stubbing parasite peut être un oubli du développeur, un artefact de copier-coller ou un effet ne comprenant pas le test/code. Dans les deux cas, le développeur se retrouve avec un code de test inutile. Afin de maintenir la base de code propre et maintenable, il est nécessaire de supprimer le code inutile. Sinon, les tests sont plus difficiles à lire et à raisonner.

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

3
sgrillon

En regardant une partie de votre trace de pile, vous avez l'impression que vous écrasez la dao.doSearch() ailleurs. Plutôt que de créer à plusieurs reprises les stubs de la même méthode.

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.

Considérez la classe de test ci-dessous par exemple:

@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
    @Mock
    Service1 svc1Mock1;

    @Mock
    Service2 svc2Mock2;

    @InjectMock
    TestClass class;

    //Assume you have many dependencies and you want to set up all the stubs 
    //in one place assuming that all your tests need these stubs.

    //I know that any initialization code for the test can/should be in a 
    //@Before method. Lets assume there is another method just to create 
    //your stubs.

    public void setUpRequiredStubs() {
        when(svc1Mock1.someMethod(any(), any())).thenReturn(something));
        when(svc2Mock2.someOtherMethod(any())).thenReturn(somethingElse);
    }

    @Test
    public void methodUnderTest_StateUnderTest_ExpectedBehavior() {
        // You forget that you defined the stub for svcMock1.someMethod or 
        //thought you could redefine it. Well you cannot. That's going to be 
        //a problem and would throw your UnnecessaryStubbingException.
       when(svc1Mock1.someMethod(any(),any())).thenReturn(anyThing);//ERROR!
       setUpRequiredStubs();
    }
}

Je préférerais envisager de refactoriser vos tests pour les remplacer si nécessaire.

3
railomaya

Si vous utilisez ce style à la place:

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

remplacez-le par:

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

Pour moi, ni les suggestions @Rule, ni les suggestions @RunWith(MockitoJUnitRunner.Silent.class) n'ont fonctionné. C'était un projet hérité où nous avons migré 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 et de lancer les tests;) 

0
philonous

Dans le cas d'un grand projet, il est difficile de corriger chacune de ces exceptions. Dans le même temps, l'utilisation de Silent n'est pas conseillée. J'ai écrit un script pour supprimer tous les coups inutiles donnés une liste d'entre eux.

https://Gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b

Nous devons simplement copier-coller la sortie mvn et écrire la liste de ces exceptions en utilisant regex et laisser le script se charger du reste.

0
mohitmayank

J'avais UnnecessaryStubbingException lorsque j'ai essayé d'utiliser les méthodes when sur un objet Spy. Mockito.lenient() a fait taire l'exception, mais les résultats du test n'étaient pas corrects.

Dans le cas d'objets Spy, il faut appeler les méthodes directement.

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
class ArithmTest {

    @Spy
    private Arithm arithm;

    @Test
    void testAddition() {

        int res = arithm.add(2, 5);

        // doReturn(7).when(arithm).add(2, 5);
        assertEquals(res, 7);
    }
}
0
Jan Bodnar