Mockito - 零与模拟的互动 - Singleton

时间:2016-12-15 06:33:49

标签: java unit-testing singleton mockito

前提条件

我有以下课程(虚构,仅用于演示问题):

public class MySingleton {

  private static MySingleton sMySingleton;
  private static List<String> sItemList;

  private MySingleton(List<String> list) {
      sItemList = list;
  }

  public static MySingleton getInstance(List<String> list) {
      if (sMySingleton == null) {
          sMySingleton = new MySingleton(list);
      }
      return sMySingleton;
  }

  public void addItem(String item) {
      sItemList.add(item);
  }

  public void removeItem(String item) {
      sItemList.remove(item);
  }
}

一个相应的测试类:

public class MySingletonTest {

  private MySingleton mInstance;
  private List<String> mList;

  @Before
  public void setup() {
      mList = mock(List.class);
      mInstance = MySingleton.getInstance(mList);
  }

  @Test
  public void testAddItem() throws Exception {
      String item = "Add";
      mInstance.addItem(item);
      verify(mList, times(1)).add(item);
  }

  @Test
  public void testRemoveItem() throws Exception {
      String item = "Remove";
      mInstance.removeItem(item);
      verify(mList, times(1)).remove(item);
  }
}

问题

如果我现在执行完整的测试类,Mockito告诉我测试testRemoveItem()与模拟有0次交互。

这怎么可能?

注意:
请不要开始讨论感觉单身人士。 这个问题是关于Mockito以及为什么它不起作用。

1 个答案:

答案 0 :(得分:1)

JUnit为每个测试创建一个新的测试类实例,Mockito为每个测试填充一个新的模拟实例。但是,您的单身人士只会初始化一次,这意味着在第一次测试期间mList == MySingleton.sItemList,但在此之后每次测试都会mList != MySingleton.sItemList

换句话说,互动正在发生,但是通过第二次测试,你会检查错误的模拟。

虽然我知道你并不是在这里讨论这种单身人士的优点,但请记住,如果你这样做,你可能很难在测试中替换实例。相反,请考虑使单例的构造函数(仅)可用于您的测试,并在实例中保持List(或其他状态)。这样你就可以创造一个全新的&#34; Singleton&#34;对于每个单独的测试。