web-dev-qa-db-fra.com

simuler les appels de méthode imbriqués à l'aide de mockito

J'ai 4 classes, dit A, B, C, D, chacune appelant des méthodes d'une autre.

maintenant je me suis moqué de la classe A et je veux me moquer d'une méthode en utilisant mockito

A a = Mockito.mock(A.class);

et veulent obtenir "foo" sur les appels de méthode récursifs comme

a.getB().getC().getD() devrait retourner "foo"

J'ai essayé

when (a.getB (). getC (). getD ()). thenReturn ("foo");

mais a obtenu nullPointerException

alors j'ai essayé

doReturn ("foo"). when (a.getB (). getC (). getD ());

alors j'ai eu org.mockito.exceptions.misusing.UnfinishedStubbingException:

Je sais que je peux créer des objets en B, C et D, ou même écrire quelque chose comme

B b = maquette (B.class) ou A.setB (nouveau B ())

etc.

Mais je ne peux pas faire ça en un seul coup? Toute aide serait appréciée.

24
Abhijeet

D'après les commentaires:

L'ajout de RETURNS_DEEP_STUBS a fait l'affaire:

A a = Mockito.mock(A.class, Mockito.RETURNS_DEEP_STUBS);
45
Abhijeet

La réponse technique d'Abhijeet est techniquement correcte, mais il est important de comprendre: vous ne devriez pas faire cela.

Votre code de "production" est fortement violant la loi de Déméter : votre classe A devrait ne sait pas qu'il doit obtenir un B pour obtenir un C pour obtenir un D.

Cela conduit simplement à un couplage super serré entre toutes ces classes. Pas une bonne idée.

Dans ce sens: vous devriez voir que le fait de devoir faire des choses spéciales ici pour que votre test fonctionne est en fait une indication que votre code de production fait quelque chose qui est hors de la normale .

Donc, au lieu de "réparer" votre configuration de test, envisagez de résoudre le vrai problème . Et c'est le design de votre code de production!

Et pour mémoire: getB (). GetC (). GetD () n'est pas un appel "récursif"; il s'agit plutôt d'un enchaînement "fluide" d'appels de méthode. Et comme dit: c'est pas une bonne chose.

11
GhostCat

Essayez de créer une maquette de chacun des objets imbriqués, puis simulez la méthode individuelle appelée par chacun de ces objets.

Si le code cible est comme:

public Class MyTargetClass {

    public String getMyState(MyClass abc){

       return abc.getCountry().getState();
    }
}

Ensuite, pour tester cette ligne, nous pouvons créer des maquettes de chacun des objets imbriqués individuels comme ci-dessous:

public Class MyTestCase{

@Mock
private MyTargetClass myTargetClassMock;

@Mock
private MyClass myclassMockObj;

@Mock
private Country countryMockObj;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

    @Test
    public void test01(){

       when(myclassMockObj.getCountry()).thenReturn(countryMockObj);
       when(countryMockObj.getState()).thenReturn("MY_TEST_STATE");
       Assert.assertEquals("MY_TEST_STATE", myTargetClassMock.getMyState(myclassMockObj));
    }
}
1
Nags