3 votes

Mock spliterator for Iterable implementation when called several times?

J'ai un problème pour simuler une classe Iterable combinée à un appel de spliterator(). Tout fonctionne bien lors de l'appel de spliterator une fois, mais le deuxième appel ne renvoie aucune valeur.

Comme le mock retourne toujours la même instance de Spliterator, je suppose que l'état n'est pas réinitialisé. Existe-t-il un moyen de faire cela?

Voici le plus petit exemple que j'ai pu donner

L'appel à mapStringToHash est une Lib dans la vraie vie et ne peut pas être modifié. MyIterable est également un objet qui n'est pas sous mon contrôle.

package net.test;

import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.MatcherAssert.assertThat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SpliteratorTest {

    class MyIterable implements Iterable {

        private List list;

        MyIterable(List list) {
            this.list = new ArrayList<>(list);
        }

        @Override
        public Iterator iterator() {
            return list.iterator();
        }

        @Override
        public Spliterator spliterator() {
            return list.spliterator();
        }
    }

    // this a library method
    private Stream mapStringToHash(final MyIterable myIterable) {
        return StreamSupport.stream(myIterable.spliterator(), false).map(String::hashCode);
    }

    @Test
    public void testSeveralSpliteratorCalls() {
        MyIterable myIterable = givenMyIterableMock("a", "b", "c");

        Stream myIterableHash1 = mapStringToHash(myIterable);
        assertThat(myIterableHash1.count(), is(3L));

        Stream myIterableHash2 = mapStringToHash(myIterable);
        assertThat(myIterableHash2.count(), is(3L));
    }

    private MyIterable givenMyIterableMock(String... values) {
        MyIterable myIterable = mock(MyIterable.class);

        Spliterator myIterableSpliterator = Arrays.stream(values)
                .collect(toList())
                .spliterator();
        doReturn(myIterableSpliterator).when(myIterable).spliterator();
        return myIterable;
    }
}

5voto

Tomasz Linkowski Points 3318

Il s'avère que ce n'est pas aussi contournable que je le pensais. Cela peut être fait en utilisant une implémentation personnalisée de Answer, mais puisque Answer est une interface fonctionnelle, ce qui suit suffit :

Mockito.when(myIterable.spliterator()).then(invocation -> Arrays.spliterator(values));

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