web-dev-qa-db-fra.com

Comment demander à un objet fictif Mockito de renvoyer quelque chose de différent lors de son prochain appel?

Donc, je crée un objet fictif en tant que variable statique au niveau de la classe, comme suit ... Dans un test, je veux que Foo.someMethod() renvoie une certaine valeur, tandis que dans un autre test, je veux qu'il renvoie un valeur différente. Le problème que j'ai, c'est qu'il semble que j'ai besoin de reconstruire les simulacres pour que cela fonctionne correctement. J'aimerais éviter de reconstruire les simulacres et utiliser simplement les mêmes objets dans chaque test.

class TestClass {

    private static Foo mockFoo;

    @BeforeClass
    public static void setUp() {
        mockFoo = mock(Foo.class);
    }

    @Test
    public void test1() {
        when(mockFoo.someMethod()).thenReturn(0);

        TestObject testObj = new TestObject(mockFoo);

        testObj.bar(); // calls mockFoo.someMethod(), receiving 0 as the value

    }

    @Test
    public void test2() {
        when(mockFoo.someMethod()).thenReturn(1);

        TestObject testObj = new TestObject(mockFoo);

        testObj.bar(); // calls mockFoo.someMethod(), STILL receiving 0 as the value, instead of expected 1.

    }

}

Dans le deuxième test, je reçois toujours 0 comme valeur lorsque testObj.bar () est appelé ... Quel est le meilleur moyen de résoudre ce problème? Notez que je sais que je pourrais utiliser un modèle différent de Foo dans chaque test. Toutefois, je dois chaîner plusieurs requêtes à partir de mockFoo, ce qui signifie que je devrais effectuer l'enchaînement dans chaque test.

171
Polaris878

Tout d'abord, ne faites pas la maquette statique. Faites-en un champ privé. Il suffit de mettre votre classe setUp dans le @Before pas @BeforeClass. Il peut être couru un tas, mais c'est bon marché.

Deuxièmement, la façon dont vous l'avez maintenant est la bonne façon d'obtenir une maquette pour renvoyer quelque chose de différent en fonction du test.

41
shoebox639

Vous pouvez également Appels consécutifs stub (# 10 dans 2.8.9 api). Dans ce cas, vous utiliseriez plusieurs appels thenReturn ou un appel thenReturn avec plusieurs paramètres (varargs).

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;

public class TestClass {

    private Foo mockFoo;

    @Before
    public void setup() {
        setupFoo();
    }

    @Test
    public void testFoo() {
        TestObject testObj = new TestObject(mockFoo);

        assertEquals(0, testObj.bar());
        assertEquals(1, testObj.bar());
        assertEquals(-1, testObj.bar());
        assertEquals(-1, testObj.bar());
    }

    private void setupFoo() {
        mockFoo = mock(Foo.class);

        when(mockFoo.someMethod())
            .thenReturn(0)
            .thenReturn(1)
            .thenReturn(-1); //any subsequent call will return -1

        // Or a bit shorter with varargs:
        when(mockFoo.someMethod())
            .thenReturn(0, 1, -1); //any subsequent call will return -1
    }
}
404
Tony R

Pour tous ceux qui cherchent à renvoyer quelque chose, puis une autre exception de lancement d'appel:

    when(mockFoo.someMethod())
            .thenReturn(obj1)
            .thenReturn(obj2)
            .thenThrow(new RuntimeException("Fail"));

ou

    when(mockFoo.someMethod())
            .thenReturn(obj1, obj2)
            .thenThrow(new RuntimeException("Fail"));
12
Nagy Attila

Pour tous ceux qui utilisent spy () et la méthode doReturn () à la place de la méthode when ():

voici ce dont vous avez besoin pour renvoyer un objet différent sur différents appels:

doReturn(obj1).doReturn(obj2).when(this.client).someMethod();
8
fl0w

Ou encore plus propre:

when(mockFoo.someMethod()).thenReturn(obj1, obj2);
7
Pedro H