web-dev-qa-db-fra.com

Comment puis-je me moquer des méthodes de la classe @InjectMocks?

Par exemple j'ai handler:

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  public int someMethod() {
    ...
    return anotherMethod();
  }

  public int anotherMethod() {...}
}

pour le tester, je veux écrire quelque chose comme ceci:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @InjectMocks
  private MyHandler myHandler;

  @Mock
  private MyDependency myDependency;

  @Test
  public void testSomeMethod() {
    when(myHandler.anotherMethod()).thenReturn(1);
    assertEquals(myHandler.someMethod() == 1);
  }
}

Mais il appelle réellement anotherMethod() chaque fois que j'essaie de me moquer de lui. Que dois-je faire avec myHandler pour se moquer de ses méthodes?

40
Vova Yatsyk

Tout d'abord, la raison de se moquer des méthodes MyHandler peut être la suivante: nous testons déjà anotherMethod() et sa logique est complexe, alors pourquoi devons-nous le tester à nouveau (comme une partie de someMethod()) si nous pouvons simplement verify l'appeler?
Nous pouvons le faire à travers: 

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @Spy  
  @InjectMocks  
  private MyHandler myHandler;  

  @Mock  
  private MyDependency myDependency;  

  @Test  
  public void testSomeMethod() {  
    doReturn(1).when(myHandler).anotherMethod();  
    assertEquals(myHandler.someMethod() == 1);  
    verify(myHandler, times(1)).anotherMethod();  
  }  
}  

Remarque: en cas d'objet 'd'espionnage', nous devons utiliser doReturn au lieu de thenReturn (peu d'explication est ici )

74
Vova Yatsyk

Dans votre code, vous ne testez pas du tout MyHandler. Vous ne voulez pas vous moquer de ce que vous testez, vous voulez appeler ses méthodes réelles. Si MyHandler a des dépendances, vous vous en moquez.

Quelque chose comme ça:

public interface MyDependency {
  public int otherMethod();
}

public class MyHandler {
  @AutoWired
  private MyDependency myDependency;

  public void someMethod() {
    myDependency.otherMethod();
  }
}

Et en test:

private MyDependency mockDependency;
private MyHandler realHandler;

@Before
public void setup() {
   mockDependency = Mockito.mock(MyDependency.class);
   realHandler = new MyHandler();
   realhandler.setDependency(mockDependency); //but you might Springify this 
}

@Test
public void testSomeMethod() {

  //specify behaviour of mock
  when(mockDependency.otherMethod()).thenReturn(1);

  //really call the method under test
  realHandler.someMethod();
}

Le but est vraiment d'appeler la méthode sous test, mais de se moquer de leurs dépendances éventuelles (par exemple, en appelant une autre classe)

Si ces autres classes font partie de votre application, elles auront leurs propres tests unitaires.

NOTEle code ci-dessus pourrait être raccourci avec plus d'annotations, mais je voulais le rendre plus explicite pour des raisons d'explication (et je ne me souviens pas en quoi consistent les annotations :)) 

0
NickJ