使用 JMockit 模拟私有静态字段?

2022-09-04 01:23:32

我有一个像下面这样的类;

class ClassA {
    private static File myDir;

    // myDir is created at some stage

    private static String findFile(final String fileName) {
       for (final String actualBackupFileName : myDir.list()) {
           if (actualBackupFileName.startsWith(removeExtensionFrom(backupFile))) {
               return actualBackupFileName;
            }
       }
    }
}

所以,基本上,我想通过模拟File类来测试这个类,这样当list()被调用时,它会返回我在测试类中定义的字符串列表。

我有以下内容,但它目前无法正常工作,可能有一些明显的事情我做错了 - 我是JMockit的新手 - 任何帮助都非常感谢!

@Mocked("list") File myDir;

@Test
  public void testClassA() {
    final String[] files = {"file1-bla.txt"};

    new NonStrictExpectations() {{
      new File(anyString).list(); 
      returns(files);
   }};

   String returnedFileName = Deencapsulation.invoke(ClassA.class, "findFile","file1.txt");

   // assert returnedFileName is equal to "file1-bla.txt"
  }

运行上述测试时,我为ClassA中的myDir字段获得了NullPointerException - 所以看起来它没有被正确地嘲笑?


答案 1

可以使用 Deencapsulation 类中的 setField 方法。请注意以下示例:

Deencapsulation.setField(ClassA, "File", your_desired_value);

答案 2

JMockit(或任何其他模拟工具)不模拟字段或变量,它模拟类型(类,接口等)。这些类型的实例存储在受测代码中的位置无关紧要。

测试示例:ClassA

@Test
public void testClassA(@Mocked File myDir)
{
    new Expectations() {{ myDir.list(); result = "file1-bla.txt"; }};

    String returnedFileName = new ClassA().publicMethodThatCallsFindFile("file1.txt");

    assertEquals("file1-bla.txt", returnedFileName);
}

以上应该有效。请注意,直接测试方法(或访问字段)被认为是不好的做法,所以我在这里避免了它。另外,最好避免嘲笑班级。相反,请仅测试您的方法,并使用实际文件,而不是模拟文件系统。privateprivateFilepublic


推荐