2010-11-18 1 views
132

Quindi, sto creando un oggetto mock come variabile statica sul livello di classe in questo modo ... In un test, voglio Foo.someMethod() per restituire un determinato valore, mentre in un altro test, voglio che restituisca un valore diverso . Il problema che sto avendo è che sembra che ho bisogno di ricostruire i mock per farlo funzionare correttamente. Mi piacerebbe evitare di ricostruire i mock e usare solo gli stessi oggetti in ogni test.Come dire a un oggetto mockito mockito di restituire qualcosa di diverso la prossima volta che viene chiamato?

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. 

    } 

} 

Nella seconda prova, sto ancora ricevendo 0 come valore quando testObj.bar() si chiama ... Qual è il modo migliore per risolvere questo? Nota che so che potrei usare un diverso simulato di Foo in ogni test, tuttavia, devo concatenare più richieste su mockFoo, il che significa che dovrei fare il concatenamento in ogni test.

risposta

36

Prima di tutto non rendere il simulatore statico. Rendilo un campo privato. Inserisci la tua classe setUp nello @Before non @BeforeClass. Potrebbe essere un gruppo, ma è economico.

In secondo luogo, il modo in cui lo hai in questo momento è il modo corretto per ottenere una simulazione di restituire qualcosa di diverso a seconda del test.

341

Si potrebbe anche Stub Consecutive Calls (# 10 in 2.8.9 api). In questo caso, si useranno più chiamate , poi Ripristina o una chiamata e poi Ripristina con più parametri (vararg).

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 
    } 
} 
+6

Nizza . Non lo sapevo. – OliverS

+1

Questo ha risolto la mia domanda, grazie Tony! – seanhodges

+140

Penso che si possa anche sfruttare il fatto che .thenReturn() prende varargs, quindi il codice può essere abbreviato in: when (mockFoo.someMethod()). ThenReturn (0, 1, -1); –

0

per chiunque utilizzi spia() e il doReturn() invece del metodo quando():

ciò che è necessario per ritornare oggetto diverso su diverse chiamate è questo:

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