¿Cómo decirle a un objeto Mockito mock que devuelva algo diferente la próxima vez que se llame?


Por lo tanto, estoy creando un objeto simulado como una variable estática en el nivel de clase como así... En una prueba, quiero que Foo.someMethod() devuelva un cierto valor, mientras que en otra prueba, quiero que devuelva un valor diferente. El problema que tengo es que parece que necesito reconstruir las burlas para que esto funcione correctamente. Me gustaría evitar reconstruir las burlas, y usar los mismos objetos en cada prueba.

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.

    }

}

En la segunda prueba, todavía estoy recibiendo 0 como el valor cuando testObj.se llama bar ()... ¿Cuál es la mejor manera de resolver esto? Tenga en cuenta que sé que podría usar un simulacro diferente de Foo en cada prueba, sin embargo, tengo que encadenar múltiples solicitudes de mockFoo, lo que significa que tendría que hacer el encadenamiento en cada prueba.

Author: Polaris878, 2010-11-18

4 answers

En primer lugar, no hagas la simulación estática. Que sea un campo privado. Simplemente ponga su clase de configuración en el @Before no @BeforeClass. Podría ser un montón, pero es barato.

En segundo lugar, la forma en que lo tienes ahora es la forma correcta de obtener un simulacro para devolver algo diferente dependiendo de la prueba.

 39
Author: shoebox639,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-18 15:45:52

También podrías Stub Llamadas Consecutivas (#10 en 2.8.9 api). En este caso, usaría múltiples llamadas y luego Retorn o una llamada y luego Retorn con múltiples parámetros (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
    }
}
 365
Author: Tony R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-31 10:42:00

Para todos los que buscan devolver algo y luego para otra llamada lanzar excepción:

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

O

    when(mockFoo.someMethod())
            .thenReturn(obj1, obj2)
            .thenThrow(new RuntimeException("Fail"));
 3
Author: Nagy Attila,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 12:09:04

Para cualquiera que use spy () y doReturn () en lugar del método when ():

Lo que necesita para devolver diferentes objetos en diferentes llamadas es esto:

doReturn(obj1).doReturn(obj2).when(this.client).someMethod();
 2
Author: fl0w,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-07 16:41:43