模拟:WrongTypeOfReturnValue (JAVA)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23697622/
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: WrongTypeOfReturnValue (JAVA)
提问by Babyburger
I've only recently started using Mockito (or mocking/stubbing for that matter). I'm starting to get the hang on how to mock objects, but I'm stuck on the following code:
我最近才开始使用 Mockito(或嘲笑/存根)。我开始了解如何模拟对象,但我坚持使用以下代码:
public class ConveyorBeltTest {
private Layout layout;
@Mock private WorkStation station1;
@Mock private WorkStation station2;
@Mock private WorkStation station3;
@Mock private CarAssemblyProcess car1;
@Mock private CarAssemblyProcess car2;
@Before
public void setUp() {
layout = new Layout();
layout.getWorkStations().add(station1);
layout.getWorkStations().add(station2);
layout.getWorkStations().add(station3);
when(station1.retrievePendingTasks().size()).thenReturn(0);
when(station2.retrievePendingTasks().size()).thenReturn(2);
when(station3.retrievePendingTasks().size()).thenReturn(1);
when(station1.getCar()).thenReturn(car1);
// it's impossible to have a car in a workstation and to have pending tasks, but it's tested regardless
when(station2.getCar()).thenReturn(car2);
when(station3.getCar()).thenReturn(null);
}
The following line throws:
以下行抛出:
// line causing the problem
when(station1.retrievePendingTasks().size()).thenReturn(0);
// error msg
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Integer cannot be returned by retrievePendingTasks()
retrievePendingTasks() should return Set
It's obviously telling me that it can't recognize station1.retrievePendingTasks() because station1 is not a real object but a mock. But I figured if I had a mock, I could chain commands behind the mock, which all wouldn't matter as long as I give the expected end result in thenReturn(). Can someone clarify what I did wrong here exactly?
它显然告诉我它无法识别 station1.retrievePendingTasks() 因为 station1 不是一个真实的对象而是一个模拟。但是我想如果我有一个模拟,我可以在模拟后面链接命令,只要我在 thenReturn() 中给出预期的最终结果,这一切都无关紧要。有人可以澄清我在这里做错了什么吗?
I have also tried with:
我也试过:
doReturn(0).when(station1).retrievePendingTasks().size();
but the result is the same.
但结果是一样的。
The workaround I have found is to make a new Set, fill it with mock elements and pass that to the result of retrievePendingTasks() for each station. This works, though that's quite a bit of extra code clogging up the screen when my only goal is to have a number for the size of the set.
我发现的解决方法是创建一个新的 Set,用模拟元素填充它并将其传递给每个站的retrievePendingTasks() 的结果。这是有效的,尽管当我的唯一目标是获得一个集合大小的数字时,有相当多的额外代码堵塞了屏幕。
采纳答案by Nathan Hughes
You're skipping over mocking what retrievePendingTasks returns and directly mocking what the thing returned by that method does. If you change the code to
您跳过了嘲笑retrievePendingTasks 返回的内容并直接嘲笑该方法返回的内容的作用。如果您将代码更改为
when(station1.retrievePendingTasks()).thenReturn(new HashSet());
or something similar, then the size of the returned set will take care of itself.
或类似的东西,那么返回的集合的大小将自行处理。
If all you need is the size then you could make a mock implementation of the Set. Or you could use the deep stubs approach in skegg99's answer. Interestingly there's a caveat in the API documentation:
如果您只需要大小,那么您可以制作 Set 的模拟实现。或者您可以在skegg99's answer 中使用深存根方法。有趣的是,API 文档中有一个警告:
WARNING: This feature should rarely be required for regular clean code! Leave it for legacy code. Mocking a mock to return a mock, to return a mock, (...), to return something meaningful hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).
警告:常规干净代码很少需要此功能!将其留给遗留代码。模拟模拟返回模拟,返回模拟,(...),返回一些有意义的暗示违反迪米特定律或模拟值对象(众所周知的反模式)。
Mocking things that don't have dependencies, especially things like Java collections that are common building blocks, is usually unnecessary and will make your tests fragile. For instance here, if you change the code to determine the size some other way then your tests will break. if the code under test changes to use an iterator and doesn't test size directly then your test breaks. Or if there are other consequences of having an empty set then you'll have to mock those separately and end up doing a lot more work, and again risk breakage if the implementation changes. I try not to mock unnecessarily.
模拟没有依赖关系的东西,尤其是像 Java 集合这样的常见构建块,通常是不必要的,并且会使您的测试变得脆弱。例如在这里,如果您更改代码以其他方式确定大小,那么您的测试将中断。如果被测代码更改为使用迭代器并且不直接测试大小,那么您的测试就会中断。或者如果有一个空集还有其他后果,那么你将不得不单独模拟它们并最终做更多的工作,如果实现发生变化,再次冒着破坏的风险。我尽量不要不必要地嘲笑。