2010-11-18 9 views
132

So erstellen ich ein Mock-Objekt als eine statische Variable auf Klassenebene wie folgt ... In einem Test möchte ich Foo.someMethod() einen bestimmten Wert zurückgeben, während ich in einem anderen Test möchte, dass es einen anderen Wert zurückgibt . Das Problem, das ich habe, ist, dass es scheint, dass ich die Mocks neu aufbauen muss, damit dies richtig funktioniert. Ich möchte es vermeiden, die Mocks neu aufzubauen, und benutze einfach die gleichen Objekte in jedem Test.Wie kann man einem Mockito-Mock-Objekt sagen, dass es beim nächsten Aufruf etwas anderes zurückgibt?

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. 

    } 

} 

Im zweiten Test, bin ich immer noch empfangen 0 als Wert, wenn testObj.bar() aufgerufen wird ... Was ist der beste Weg, dies zu lösen? Beachten Sie, dass ich weiß, dass ich einen anderen Mock von Foo in jedem Test verwenden könnte, jedoch muss ich mehrere Anfragen von mockFoo verketten, was bedeutet, dass ich die Verkettung in jedem Test durchführen müsste.

Antwort

36

Zuerst machen Sie den Schein nicht statisch. Machen Sie es zu einem privaten Bereich. Setzen Sie Ihre Setup-Klasse in die @Before nicht @BeforeClass. Es könnte ein Haufen laufen, aber es ist billig.

Zweitens ist die Art und Weise, wie Sie es jetzt haben, der richtige Weg, um einen Mock zu bekommen, der je nach Test etwas anderes zurückgibt.

341

Sie könnten auch Stub Consecutive Calls (# 10 in 2.8.9 API). In diesem Fall würden Sie mehrere thenReturn Anrufe oder einen thenReturn Aufruf mit mehreren Parametern (varargs) verwenden.

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 . Wusste das nicht. – OliverS

+1

Das hat meine Frage gelöst, danke Tony! – seanhodges

+140

Ich denke, Sie können auch die Tatsache nutzen, dass .thenReturn() varargs verwendet, so dass der Code wie folgt verkürzt werden kann: when (mockFoo.someMethod()). ThenReturn (0, 1, -1); –

0

für jedermann unter Verwendung Spion() und die doReturn() anstelle des bei() -Methode:

, was Sie brauchen anderes Objekt auf verschiedenen Anrufe zurückzukehren, ist dies:

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