mockito:WrongTypeOfReturnValue(JAVA)

时间:2014-05-16 14:19:15

标签: java testing junit mockito

我最近才开始使用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()的结果。这是有效的,但是当我的唯一目标是获得一组数量的数字时,这是相当多的额外代码堵塞屏幕。

2 个答案:

答案 0 :(得分:4)

我相信它被称为深层存根,需要特别小心。您可以使用this方法并添加

@Mock(answer=Answers.RETURNS_DEEP_STUBS)

但是,为了避免这种情况,重写测试会更好

答案 1 :(得分:1)

您正在跳过嘲笑retrievePendingTasks返回的内容,并直接模拟该方法返回的内容。如果您将代码更改为

when(station1.retrievePendingTasks()).thenReturn(new HashSet());

或类似的东西,然后返回的集合的大小将自行处理。

如果您需要的只是大小,那么您可以进行Set的模拟实现。或者您可以在skegg99's answer中使用深层存根方法。有趣的是,API documentation中有一个警告:

  

警告:常规清洁代码很少需要此功能!留下遗留代码。模拟一个模拟返回一个模拟,返回一个模拟,(...),返回违反Demeter法则或模拟一个值对象(一个众所周知的反模式)的有意义的提示。

模拟没有依赖关系的东西,尤其是像常见构建块的Java集合这样的东西,通常是不必要的,会使你的测试变得脆弱。例如,如果您更改代码以确定其他方式的大小,那么您的测试将会中断。如果测试中的代码更改为使用迭代器并且不直接测试大小,那么测试会中断。或者,如果有一个空集的其他后果,那么你将不得不分别嘲笑那些并最终做更多的工作,如果实施改变,再次冒险破坏。我尽量不要不必要地嘲笑。