【问题标题】:Mocking objects for JUnit test用于 JUnit 测试的模拟对象
【发布时间】:2018-01-15 08:22:35
【问题描述】:

我正在编写一个Junit来测试Client.java中的以下方法:

public FSDataInputStream getObj(String hName, Path p) throws IOException {

    String myKey = pathToKey(hName, p);
    FileStatus status = memoryCache.getStatus(p.toString());
    if (status == null) {
      status = getStatus(hName, p, "getObject");
    }
    if (status.isDirectory()) {
      throw new FileNotFoundException("Can't open " + path
      + " because it is a directory");
    }
    InputStream inputStream = new InputStream(bucket, myKey,
        status.getLen(), client, readAhead, inputPolicy);

    return new FSDataInputStream(inputStream);
}

最初我想测试如果status == null然后getStatus()被调用,如果status.isDirectory(),则抛出FileNotFoundException

我是 Junit 的新手,所以不完全确定自己在做什么,但据我所知,我认为我需要模拟以下内容:

  1. 列表项
  2. 客户
  3. 状态
  4. 输入流
  5. 可能是内存缓存

到目前为止,这是我所拥有的:

@Before
public final void before() {
    private COSAPIClient myClient;
    private String myBucket;
    FileStatus myStatus;
    InputStream myInputStream;

    myClient = PowerMockito.mock(AmazonS3.class);
    myInputStream = PowerMockito.mock(InputStream.class);
    myFileStatus = PowerMockito.mock(FileStatus.class);
}

@Test
public void getObjTest() throws Exception {
    URI uri = new URI("xyz://aa-bb-cc/data7-1-23-a.txt");
    String hName = "xyz://aa-bb-cc/";
    Path p = new Path("cos://aa-bb-cc/data7-1-23-a.txt");

    Configuration conf = new Configuration();

    myClient = spy(new Client(uri, conf));
    myStatus = spy(new FileStatus());
    myMemoryCache.getStatus(p.toString());

    InputStream = spy(new InputStream(myBucket, objectKey, 300, myClient, 12345678910L, myInputPolicy));
}

它在我的程序的这一行返回一个 NullPointerError:

FileStatus status = memoryCache.getStatus(p.toString());

我想知道是否有人可以建议我是否/我做错了什么以及我应该如何解决这个问题?

【问题讨论】:

  • 3.状态 你的意思是getStatus()?
  • 什么是memoryCache?它是如何初始化/注入你的类的?你在哪里调用getObj 到你的班级?
  • 克里斯特尔斯 - 是的。 Sergii Bishyr - 我不确定你在问什么,但我确信我所做的是不正确的。

标签: java unit-testing junit mocking mockito


【解决方案1】:

首先,真正的答案:退一步。不要以 JUnit 和 Mockito 以及 您的 生产代码作为输入开始。而是查看一个教程(如here),它逐步解释了所有相关元素以及如何将它们“组合”在一起。

在您的情况下,您的代码存在各种问题:

  • 为什么要使用 PowerMock?尝试搭配“普通香草”Mockito。如果您的生产代码需要 PowerMock,请考虑返工而不是转向 PowerMock。
  • 您似乎真的不知道在哪里/如何应用模拟。换句话说:您在运行您的被测代码时模拟您需要控制的元素。如果你无法控制它们,你只使用嘲笑。含义:您几乎从不模拟列表 - 您只需创建一个“普通”列表,然后添加该列表应包含的内容。
  • 创建模拟允许调用模拟对象上的方法。但默认情况下,任何返回内容的方法都将返回 null(或者可能是一个空集合,或者对于原始返回类型为 0,请参阅here 了解详细信息)。因此,您更需要一个声明,例如 when(mockedCache.getStatus("some string")).thenReturn(someResult)

【讨论】:

  • 很好的解释。第三个要点不太对。模拟方法的默认返回值取决于它的返回类型——它并不总是返回 null。有一堆难以记住的例外,如下所示。返回 Collection 的方法将返回空,而不是默认情况下为空。返回原始类型的方法将返回 0 或 false。返回原始包装类型的方法也将返回 0 或 false。标准compareTo方法默认为1,标准toString方法默认为mock的名字。
  • 感谢 GhostCat。我会检查一下。
  • @DawoodibnKareem 谢谢。不知道 - 我相应地更新了答案。
  • 感谢@GhostCat。我将不得不在这方面做一些工作,但它非常有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
相关资源
最近更新 更多