我最近才开始使用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);
}
以下行抛出:
// 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
显然告诉我它无法识别station1.retrievePendingTasks(),因为station1不是真实对象而是模拟。但我想如果我有一个模拟器,我可以在模拟器后面链接命令,只要我在thenReturn()中给出预期的最终结果,这一切都无关紧要。有人能澄清我在这里做错了什么吗?
我也尝试过:
doReturn(0).when(station1).retrievePendingTasks().size();
但结果是一样的。
我找到的解决方法是创建一个新的Set,用mock元素填充它并将其传递给每个站的retrievePendingTasks()的结果。这是有效的,但是当我的唯一目标是获得一组数量的数字时,这是相当多的额外代码堵塞屏幕。
答案 0 :(得分:4)
答案 1 :(得分:1)
您正在跳过嘲笑retrievePendingTasks返回的内容,并直接模拟该方法返回的内容。如果您将代码更改为
when(station1.retrievePendingTasks()).thenReturn(new HashSet());
或类似的东西,然后返回的集合的大小将自行处理。
如果您需要的只是大小,那么您可以进行Set的模拟实现。或者您可以在skegg99's answer中使用深层存根方法。有趣的是,API documentation中有一个警告:
警告:常规清洁代码很少需要此功能!留下遗留代码。模拟一个模拟返回一个模拟,返回一个模拟,(...),返回违反Demeter法则或模拟一个值对象(一个众所周知的反模式)的有意义的提示。
模拟没有依赖关系的东西,尤其是像常见构建块的Java集合这样的东西,通常是不必要的,会使你的测试变得脆弱。例如,如果您更改代码以确定其他方式的大小,那么您的测试将会中断。如果测试中的代码更改为使用迭代器并且不直接测试大小,那么测试会中断。或者,如果有一个空集的其他后果,那么你将不得不分别嘲笑那些并最终做更多的工作,如果实施改变,再次冒险破坏。我尽量不要不必要地嘲笑。