如何告诉 Mockito 模拟对象在下次调用时返回不同的内容?

发布于 2024-10-02 19:09:18 字数 970 浏览 7 评论 0原文

因此,我在类级别创建一个模拟对象作为静态变量,如下所示...在一个测试中,我希望 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 上,这意味着我必须执行以下操作每个测试中的链接。

So, I'm creating a mock object as a static variable on the class level like so... In one test, I want Foo.someMethod() to return a certain value, while in another test, I want it to return a different value. The problem I'm having is that it seems I need to rebuild the mocks to get this to work correctly. I'd like to avoid rebuilding the mocks, and just use the same objects in each 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.

    }

}

In the second test, I'm still receiving 0 as the value when testObj.bar() is called... What is the best way to resolve this? Note that I know I could use a different mock of Foo in each test, however, I have to chain multiple requests off of mockFoo, meaning I'd have to do the chaining in each test.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

星星的轨迹 2024-10-09 19:09:18

您还可以 存根连续调用(2.8.9 api 中的#10)。在这种情况下,您将使用多个 thenReturn 调用或一个带有多个参数 (varargs) 的 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
    }
}

You could also Stub Consecutive Calls (#10 in 2.8.9 api). In this case, you would use multiple thenReturn calls or one thenReturn call with multiple parameters (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
    }
}
ぃ双果 2024-10-09 19:09:18

对于所有搜索返回某些内容然后再次调用抛出异常的人:

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

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

For all who search to return something and then for another call throw exception:

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

or

when(mockFoo.someMethod())
        .thenReturn(obj1, obj2)
        .thenThrow(new RuntimeException("Fail"));
闻呓 2024-10-09 19:09:18

首先不要使模拟静态。将其设为私有字段。只需将您的 setUp 类放在 @Before 中,而不是 @BeforeClass 中。它可能会运行很多,但很便宜。

其次,您现在的方式是让模拟根据测试返回不同内容的正确方法。

First of all don't make the mock static. Make it a private field. Just put your setUp class in the @Before not @BeforeClass. It might be run a bunch, but it's cheap.

Secondly, the way you have it right now is the correct way to get a mock to return something different depending on the test.

指尖微凉心微凉 2024-10-09 19:09:18

或者,更干净:

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

Or, even cleaner:

when(mockFoo.someMethod()).thenReturn(obj1, obj2);
梦一生花开无言 2024-10-09 19:09:18

对于任何使用spy()和doReturn()而不是when()方法的人:

你需要在不同的调用上返回不同的对象是这样的:

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);

For Anyone using spy() and the doReturn() instead of the when() method:

what you need to return different object on different calls is this:

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

.

For classic mocks:

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

or with an exception being thrown:

when(mockFoo.someMethod())
        .thenReturn(obj1)
        .thenThrow(new IllegalArgumentException())
        .thenReturn(obj2, obj3);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文