15

我遇到了mockito的问题。我正在开发一个网络应用程序。在我的测试中,用户管理被嘲笑了。在某些情况下,我必须更改该getLoggedInUser()方法返回的用户。

问题是,我的getLoggedInUser()方法也可以抛出AuthenticationException.

因此,当我尝试从无用户切换到某个用户时,调用

when(userProvider.getLoggedInUser()).thenReturn(user);

抛出一个异常,因为userProvider.getLoggedInUser()它已经被存根了thenTrow()

有没有办法告诉该when方法不关心异常?

提前致谢 - 伊斯特万

4

3 回答 3

21

在新的 Mockito 版本中,您可以使用存根连续调用在第一次调用时抛出异常并在第二次调用时返回值。

when(mock.someMethod("some arg"))
    .thenThrow(new RuntimeException())
    .thenReturn("foo");

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#10

于 2012-06-14T08:39:10.203 回答
5

我对您的问题的第一反应是,听起来您在一次测试中尝试做太多事情。

为了便于测试和简单,每个测试应该只测试一件事。这与单一职责原则相同。我经常发现程序员试图在一个测试中测试多个事物并因此而遇到各种问题。因此,您的每个单元测试方法都应遵循以下流程:

  1. 为测试设置一个场景。
  2. 调用正在测试的类以触发正在测试的代码。
  3. 验证行为。

所以在你的情况下,我希望看到至少两个测试。一个getLoggedInUser()返回用户,一个getLoggedInUser()抛出异常。这样你就不会在尝试模拟模拟中的不同行为时遇到问题。

第二个想法是不要存根。考虑改用期望,因为您可以设置一系列期望。即第一个调用返回一个用户,第二个调用抛出一个异常,第三个调用返回一个不同的用户,等等。

于 2010-11-14T23:30:06.667 回答
5

有没有办法告诉 when 方法不关心异常?

要真正回答这个问题:

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;

public class MyTest {

    @Test
    public void testA() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.indexOf(any())).thenReturn(6);
        when(list.indexOf(any())).thenReturn(12);

        // execute
        int index = list.indexOf(new Object());

        // verify
        assertThat(index, is(equalTo(12)));
    }

    @Test
    public void testB() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
        when(list.add(any())).thenReturn(true);

        // execute
        list.add(new Object());
    }

    @Test
    public void testC() {

        // setup
        ArrayList<Object> list = mock(ObjectArrayList.class);
        when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
        Mockito.reset(list);
        when(list.add(any())).thenReturn(true);

        // execute
        list.add(new Object());
    }

    /**
     * Exists to work around the fact that mocking an ArrayList<Object>
     * requires a cast, which causes "unchecked" warnings, that can only be suppressed...
     */
    class ObjectArrayList extends ArrayList<Object> {

    }
}

TestB由于您无法摆脱的断言而失败。TestC展示了如何reset使用该方法重置模拟并删除其thenThrow上的命令。

请注意,在我拥有的一些更复杂的示例中,重置似乎并不总是有效。我怀疑这可能是因为他们正在使用PowerMockito.mock而不是Mockito.mock

于 2017-05-11T13:36:29.927 回答