在Mockito中设置后重置模拟的正确替代方法是什么?

时间:2013-10-18 04:20:54

标签: java unit-testing mocking mockito

我是单位测试的新手,并试图学习正确的风格。我喜欢设置我正在测试的对象,以便我可以测试它,就像它正在使用而不是仅测试新构造的对象。我无法测试从空的对象中删除东西,因为构造时会有很多对象。

以下是一个测试ObservedList的示例,ListListener是一个被模拟的必要类。

public final class ObservedListTest {
  private ListListener<Integer> listener;
  private ObservedList<Integer> list;
  @BeforeMethod public void setup() {
    listener = mock(ListListener.class);
    list = new ObservedList<Integer>(listener);
    list.addAll(Arrays.asList(1,2,3));
    reset(listener);
  }
  @Test public void addFirst() {
    list.add(0, -1);
    verify(listener).listEdited(list, 0, 1, Collections.<Integer>emptyList());
    verifyNoMoreInteractions(listener);
  }
  @Test void addAtEnd() {
    list.add(9);
    verify(listener).listEdited(list, 3, 4, Collections.<Integer>emptyList());
    verifyNoMoreInteractions(listener);
  }
  @Test void removeMiddle() {
    list.remove(Integer.valueOf(2));
    verify(listener).listEdited(list, 1, 1, Collections.singletonList(2));
    verifyNoMoreInteractions(listener);
  }
}

作为一个新手,这似乎对我有用,但我知道这是不好的做法,因为它使用reset方法。我打电话给reset因为我不希望实际测试因设置中发生的交互而混淆。

reset的javadoc甚至没有告诉你该方法的作用,因为它太忙于告诉你不应该使用它。通常我只是采用这个建议,并通过删除我的reset方法并调整我的测试看起来更像这样来避免setup

  @Test void removeMiddle() {
    listener = mock(ListListener.class);
    list = new ObservedList<Integer>(listener);
    list.addAll(Arrays.asList(1,2,3));
    list.remove(Integer.valueOf(2));
    InOrder inOrder = inOrder(listener);
    inOrder.verify(listener).listEdited(list, 0, 3,
      Collections.<Integer>emptyList());
    inOrder.verify(listener).listEdited(list, 1, 1,
      Collections.singletonList(2));
    verifyNoMoreInteractions(listener);
  }

这个似乎对我有用。问题是reset方法的文档说:

  

请考虑编写简单,小巧且专注的内容,而不是重置()   测试方法超过冗长,过度指定的测试。

我尊重Mockito旨在鼓励单元测试中的好风格,我想从中学习,但我很难理清它试图发送给我的信息。当我从测试中删除reset时,我的测试得到复杂更长更少关注,所以显然我正在做错。

做得对的样子是什么样的?

2 个答案:

答案 0 :(得分:2)

删除reset。删除verifyNoMoreInteractions。问题解决了。您的测试更简单,更短,更专注。

答案 1 :(得分:1)

Mockito 2.1添加了clearInvocations方法,可以这样使用:

public final class ObservedListTest {
  private ListListener<Integer> listener;
  private ObservedList<Integer> list;

  @BeforeMethod public void setup() {
    listener = mock(ListListener.class);
    list = new ObservedList<Integer>(listener);
    list.addAll(Arrays.asList(1,2,3));
    clearInvocations(listener);
  }

  @Test public void addFirst() {
    list.add(0, -1);
    verify(listener, only()).listEdited(list, 0, 1, Collections.<Integer>emptyList());
  }

  @Test void addAtEnd() {
    list.add(9);
    verify(listener, only()).listEdited(list, 3, 4, Collections.<Integer>emptyList());
  }

  @Test void removeMiddle() {
    list.remove(Integer.valueOf(2));
    verify(listener, only()).listEdited(list, 1, 1, Collections.singletonList(2));
  }
}

请注意,clearInvocations javadoc还声明:

  

尽量避免使用此方法。如果你,只有明确的调用   无法有效地测试您的程序。