295 votes

Comment dire à un Mockito objet fantaisie pour revenir à quelque chose de différent la prochaine fois, il est appelé?

Donc, je vais créer un objet fantaisie comme une variable statique au niveau de la classe comme si... Dans un test, je veux Foo.someMethod() de renvoyer une certaine valeur, alors que dans un autre test, je le veux renvoyer une valeur différente. Le problème que je vais avoir, c'est qu'il semble que j'ai besoin de reconstruire les objets fantaisie à obtenir que cela fonctionne correctement. J'aimerais éviter la reconstruction de l'est se moquer, et il suffit d'utiliser 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 essai, je suis encore reçu 0 comme valeur lorsque testObj.bar() est appelée... Quelle est la meilleure façon de résoudre ce problème? Notez que je sais que je pourrais utiliser un autre en dérision Foo dans chaque test, cependant, j'ai de la chaîne de multiples requêtes d' mockFoo, ce qui signifie que je devrais faire de l'enchaînement dans chaque test.

550voto

Tony R Points 1678

Vous pouvez également Stub Appels Consécutifs (n ° 10 dans 1.8.5 api). Dans ce cas, vous devez utiliser plusieurs ThenReturn consolidés.

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
}

}

52voto

shoebox639 Points 1619

Tout d'abord ne pas faire de la maquette statique. En faire un champ privé. Il suffit de mettre votre installation de classe dans l' @Before pas @BeforeClass. Il peut être exécuté en un tas, mais c'est pas cher.

Deuxièmement, la façon dont vous l'avez droit maintenant est le bon moyen de se faire une maquette pour revenir à quelque chose de différent en fonction du test.

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