java Mockito 重新存根方法已经用 thenthrow 存根
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4180209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito re-stub method already stubbed with thenthrow
提问by Sobvan
I ran into a problem with mockito.
I am developing a web application. In my tests the user management is mocked.
There are some cases when I have to alter the User returned by the getLoggedInUser()
method.
我遇到了 mockito 的问题。我正在开发一个网络应用程序。在我的测试中,用户管理被嘲笑。在某些情况下,我必须更改getLoggedInUser()
方法返回的用户。
The problem is, that my getLoggedInUser()
method can also throw an AuthenticationException
.
问题是,我的getLoggedInUser()
方法也可以抛出一个AuthenticationException
.
So when I try to switch from no user to some user, the call to
因此,当我尝试从无用户切换到某个用户时,调用
when(userProvider.getLoggedInUser()).thenReturn(user);
throws an exception, as userProvider.getLoggedInUser()
is already stubbed with thenTrow()
抛出异常,因为userProvider.getLoggedInUser()
已经存根thenTrow()
Is there any way for to tell the when
method not to care about exceptions?
有什么方法可以告诉when
方法不关心异常吗?
Thanks in advance - István
提前致谢 - István
采纳答案by drekka
My first reaction to your question is that it sounds like you are trying to do too much in one test.
我对你的问题的第一反应是,听起来你在一次测试中尝试做的太多了。
For ease of testing and simplicity each test should test one thing only. This is the same as the Single Responsibility Principle. I often find programmers trying to test multiple things in one test and having all sorts of problems because of it. So each of your unit test methods should follow this flow:
为了便于测试和简单,每个测试应该只测试一件事。这与单一职责原则相同。我经常发现程序员试图在一个测试中测试多个东西,并因此遇到各种各样的问题。因此,您的每个单元测试方法都应遵循以下流程:
- Setup a single scenario for the test.
- Make a call to the class being tested to trigger the code being tested.
- Verify the behaviour.
- 为测试设置单个场景。
- 调用被测试的类来触发被测试的代码。
- 验证行为。
So in your case I would expect to see at least two tests. One where getLoggedInUser()
returns a user, and one where getLoggedInUser()
throws an exception. That way you will not have problems with trying to simulate different behaviour in the mock.
所以在你的情况下,我希望看到至少两个测试。一个getLoggedInUser()
返回用户,一个getLoggedInUser()
抛出异常。这样你就不会在模拟中尝试模拟不同的行为时遇到问题。
The second thought that spring to mind is not to stub. Look into using expect instead because you can setup a series of expectation. I.e. the first call returns a user, the second call throws an exception, the third call returns a different user, etc.
想到的第二个想法是不要存根。考虑使用 expect 代替,因为您可以设置一系列期望。即第一次调用返回一个用户,第二次调用抛出异常,第三次调用返回一个不同的用户,等等。
回答by Bogdan Sulima
In new Mockito versions you can use stubbing consecutive calls to throw exception on first can and returning a value on a second call.
在新的 Mockito 版本中,您可以使用存根连续调用在第一次调用时抛出异常并在第二次调用时返回一个值。
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#stubbing_consecutive_calls
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#stubbing_consecutive_calls
回答by Pod
Is there any way for to tell the when method not to care about exceptions?
有没有办法告诉 when 方法不关心异常?
To actually answer this question:
要真正回答这个问题:
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
fails due to the assert that you can't get rid of. TestC
shows how the reset
method can be used to reset the mock and remove the thenThrow
command on it.
TestB
由于无法摆脱的断言而失败。TestC
显示了如何使用该reset
方法重置模拟并删除其thenThrow
上的命令。
Note that reset doesn't always seem to work in some more complicated examples I have. I suspect it might be because they're using PowerMockito.mock
rather than Mockito.mock
?
请注意,在我拥有的一些更复杂的示例中,重置似乎并不总是有效。我怀疑这可能是因为他们正在使用PowerMockito.mock
而不是Mockito.mock
?
回答by javamonkey79
It sounds like you may have to use a custom answer. Here is an example.
听起来您可能必须使用自定义答案。这是一个例子。