web-dev-qa-db-fra.com

Créer une liste simulée par mockito

Je veux créer une liste simulée pour tester le code ci-dessous:

 for (String history : list) {
        //code here
    }

Voici ma mise en œuvre:

public static List<String> createList(List<String> mockedList) {

    List<String> list = mock(List.class);
    Iterator<String> iterHistory = mock(Iterator.class);

    OngoingStubbing<Boolean> osBoolean = when(iterHistory.hasNext());
    OngoingStubbing<String> osHistory = when(iterHistory.next());

    for (String history : mockedList) {

        osBoolean = osBoolean.thenReturn(true);
        osHistory = osHistory.thenReturn(history);
    }
    osBoolean = osBoolean.thenReturn(false);

    when(list.iterator()).thenReturn(iterHistory);

    return list;
}

Mais lorsque le test est lancé, il lance une exception à la ligne:

OngoingStubbing<DyActionHistory> osHistory = when(iterHistory.next());

pour plus de détails:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.PowerMockito.when(PowerMockito.Java:495)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

Comment puis-je résoudre ce problème? Merci

25
Tien Nguyen

OK, c'est une mauvaise chose à faire. Ne vous moquez pas d'une liste; au lieu de cela, mockez les objets individuels dans la liste. Voir Mockito: se moquant d'un arraylist qui sera bouclé dans une boucle for pour savoir comment faire cela.

Aussi, pourquoi utilisez-vous PowerMock? Vous ne semblez rien faire qui nécessite PowerMock.

Mais la vraie cause de votre problème est que vous utilisez when sur deux objets différents, avant de terminer le stubbing. Lorsque vous appelez when et que vous indiquez l’appel de méthode que vous essayez de remplacer, la prochaine action que vous effectuez dans Mockito OR PowerMock consiste à spécifier La méthode est appelée - c’est-à-dire faire la partie thenReturn. Chaque appel à when doit être suivi d’un seul et unique appel à thenReturn avant de pouvoir effectuer d’autres appels. à when. Vous avez fait deux appels à when sans appeler thenReturn - c'est votre erreur.

29
Dawood ibn Kareem

Lorsque je traite des listes moqueuses et les itère, j'utilise toujours quelque chose comme:

@Spy
private List<Object> parts = new ArrayList<>();
8
lyuboe

Nous pouvons nous moquer de la liste correctement pour une boucle foreach. Veuillez trouver ci-dessous l'extrait de code et l'explication.

Ceci est ma méthode de classe actuelle où je veux créer un scénario de test en moquant une liste. this.nameList Est un objet de la liste.

public void setOptions(){
    // ....
    for (String str : this.nameList) {
        str = "-"+str;
    }
    // ....
}

La boucle foreach fonctionne en interne sur un itérateur, nous avons donc créé ici un simulacre de itérateur. Le framework Mockito permet de renvoyer une paire de valeurs lors de l'appel d'une méthode particulière en utilisant Mockito.when().thenReturn(), c'est-à-dire que hasNext() passe le premier vrai et le second faux, de sorte que notre boucle ne continue que deux fois. fois. Sur next(), nous renvoyons simplement la valeur de retour réelle.

@Test
public void testSetOptions(){
    // ...
    Iterator<SampleFilter> itr = Mockito.mock(Iterator.class);
    Mockito.when(itr.hasNext()).thenReturn(true, false);
    Mockito.when(itr.next()).thenReturn(Mockito.any(String.class);  

    List mockNameList = Mockito.mock(List.class);
    Mockito.when(mockNameList.iterator()).thenReturn(itr);
    // ...
}

De cette façon, nous pouvons éviter d’envoyer la liste réelle à tester en utilisant un modèle de liste.

4
Ashish Kirpan