다음에 호출 할 때 Mockito 모의 객체에 다른 것을 반환하도록 지시하는 방법은 무엇입니까?


202

그래서 클래스 클래스에서 정적 변수로 모의 객체를 만들고 있습니다. 한 테스트에서는 Foo.someMethod()특정 값을 반환하고 다른 테스트에서는 다른 값을 반환하려고합니다. 내가 겪고있는 문제는 올바르게 작동하기 위해 모의를 재구성해야한다는 것입니다. 모형을 다시 작성하지 않고 각 테스트에서 동일한 객체를 사용하고 싶습니다.

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.

    }

}

두 번째 테스트에서 testObj.bar ()가 호출 될 때 여전히 0으로 값을받습니다 ...이 문제를 해결하는 가장 좋은 방법은 무엇입니까? Foo각 테스트에서 서로 다른 모의를 사용할 수 있다는 것을 알고 있지만 여러 요청을에서 연결 해제 mockFoo해야합니다. 즉, 각 테스트에서 연결을 수행해야합니다.

답변:


43

우선 모의를 정적으로 만들지 마십시오. 개인 필드로 만드십시오. 설정 클래스를 @Beforenot 에 넣으십시오 @BeforeClass. 무리가 될 수도 있지만 싸다.

둘째, 지금 당장 얻는 방법은 모의 시험에 따라 다른 것을 돌려주는 올바른 방법입니다.


438

또한 연속 호출을 스터브 할 수도 있습니다 (2.8.9 API에서 # 10). 이 경우 여러 매개 변수 (varargs)와 함께 여러 thenReturn 호출 또는 하나의 thenReturn 호출을 사용합니다.

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

171
또한 .thenReturn ()이 varargs를 사용하므로 코드를 단축 할 수 있다는 사실을 활용할 수 있다고 생각합니다. when (mockFoo.someMethod ()). thenReturn (0, 1, -1);
저스틴 뮬러

10
@JustinMuller -의 가치가 별도의 대답, 내가 (코멘트 반대) 생각
브라이언 애그뉴

16
이 경우에는 정답이 아닙니다. 당신이 0과 1을 반환하는이 방법을 스텁 경우에, 당신은 그래서 당신이 실행으로 괜찮을거야 test1하고 test2. 그러나 지속적인 통합 환경이 다른 순서로 테스트를 실행할 수 있습니다. 또는 먼저 test2실행하지 않고 스스로 실행하고 싶을 수도 있습니다 test1.이 경우 실패합니다. 단위 테스트 항상 서로 독립적 이어야합니다 . 거기해야 결코 개별 테스트 사이의 종속성 또는 시험의 특정 순서에 종속 될 수 없습니다. 연쇄 thenReturn성명서 ...
Dawood ibn Kareem

4
... 단일 용도로 varargs를 사용하는 것과 마찬가지로 용도가 thenReturn있습니다.이 특별한 경우에는 올바른 해결책이 아닙니다. 여기에있는 지지자들의 무리가 그 질문을 이해하지 못한 것 같습니다.
Dawood ibn Kareem

2
Junit 자체는 다음없이 테스트 주문을 보장하지 않습니다@FixMethodOrder
Roger

29

무언가를 반환 한 다음 다른 호출 예외를 검색하려는 모든 사람에게 :

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

또는

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

19

또는 더 깨끗합니다.

when(mockFoo.someMethod()).thenReturn(obj1, obj2);

2
이것이 답이되어야합니다.
Ikthiander

14

when () 메소드 대신 spy () 및 doReturn ()을 사용하는 모든 사람의 경우 :

다른 호출에서 다른 객체를 반환 해야하는 것은 다음과 같습니다.

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

.

클래식 모형의 경우 :

when(this.mockFoo.someMethod()).thenReturn(obj1, obj2);

또는 예외가 발생하는 경우 :

when(mockFoo.someMethod())
        .thenReturn(obj1)
        .thenThrow(new IllegalArgumentException())
        .thenReturn(obj2, obj3);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.