用Java模拟文件 - 模拟内容 - Mockito

Mat*_*ril 28 java file mockito

我很嘲笑,我一直在尝试模拟实际内容(本质上只在内存中创建一个虚拟文件),这样就不会在任何时候将数据写入磁盘.

我已经尝试过像模拟文件和模拟尽可能多的我可以解决的许多属性的解决方案,然后用文件编写器/缓冲区写入器写入它,但是那些不能正常工作,因为它们需要规范路径.有人找到了这个或类似的解决方案,但我接近这个错误?

我一直在这样做:

private void mocking(){
    File badHTML = mock(File.class);
    //setting the properties of badHTML
    when(badHTML.canExecute()).thenReturn(Boolean.FALSE);
    when(badHTML.canRead()).thenReturn(Boolean.TRUE);
    when(badHTML.canWrite()).thenReturn(Boolean.TRUE);
    when(badHTML.compareTo(badHTML)).thenReturn(Integer.SIZE);
    when(badHTML.delete()).thenReturn(Boolean.FALSE);
    when(badHTML.getFreeSpace()).thenReturn(0l);
    when(badHTML.getName()).thenReturn("bad.html");
    when(badHTML.getParent()).thenReturn(null);
    when(badHTML.getPath()).thenReturn("bad.html");
    when(badHTML.getParentFile()).thenReturn(null);
    when(badHTML.getTotalSpace()).thenReturn(0l);
    when(badHTML.isAbsolute()).thenReturn(Boolean.FALSE);
    when(badHTML.isDirectory()).thenReturn(Boolean.FALSE);
    when(badHTML.isFile()).thenReturn(Boolean.TRUE);
    when(badHTML.isHidden()).thenReturn(Boolean.FALSE);
    when(badHTML.lastModified()).thenReturn(System.currentTimeMillis());
    when(badHTML.mkdir()).thenReturn(Boolean.FALSE);
    when(badHTML.mkdirs()).thenReturn(Boolean.FALSE);
    when(badHTML.setReadOnly()).thenReturn(Boolean.FALSE);
    when(badHTML.setExecutable(true)).thenReturn(Boolean.FALSE);
    when(badHTML.setExecutable(false)).thenReturn(Boolean.TRUE);
    when(badHTML.setReadOnly()).thenReturn(Boolean.FALSE);

    try {
        BufferedWriter bw = new BufferedWriter(new FileWriter(badHTML));
        /*
          badHTMLText is a string with the contents i want to put into the file, 
          can be just about whatever you want
         */
        bw.append(badHTMLText);
        bw.close();

    } catch (IOException ex) {
        System.err.println(ex);
    }
}
Run Code Online (Sandbox Code Playgroud)

任何想法或指导都会非常有帮助.在此之后的某个地方我基本上尝试使用另一个类从文件中读取.我会尝试模拟某种输入流,但另一类不接受输入流,因为它是项目的io处理类.

Jef*_*ica 63

你似乎追求矛盾的目标.一方面,您试图避免将数据写入磁盘,这在测试中并不是一个糟糕的目标.另一方面,您正在尝试测试您的I/O处理类,这意味着您将使用系统实用程序,假设您File将使用本机调用.因此,这是我的指导:

  • 不要试图嘲笑File.只是不要.太多的原生物取决于它.
  • 如果可以的话,将I/O处理代码拆分为打开a的一半File并将其转换为a Reader,将解析HTML的一半转换为a Reader.
  • 此时,您根本不需要模拟 - 只需构造一个StringReader模拟数据源.
  • 虽然它可以很好地处理您的单元测试,但您可能还希望编写一个使用临时文件集成测试,并确保其正确读取.(感谢Brice添加该提示!)

不要害怕重构你的课程以使测试更容易,如下所示:

class YourClass {
  public int method(File file) {
    // do everything here, which is why it requires a mock
  }   
}   

class YourRefactoredClass {
  public int method(File file) {
    return methodForTest(file.getName(), file.isFile(),
        file.isAbsolute(), new FileReader(file));
  }   

  /** For testing only. */
  int methodForTest(
      String name, boolean isFile, boolean isAbsolute, Reader fileContents) {
    // actually do the calculation here
  }   
}   

class YourTest {
  @Test public int methodShouldParseBadHtml() {
    YourRefactoredClass yrc = new YourRefactoredClass();
    assertEquals(42, yrc.methodForTest(
        "bad.html", true, false, new StringReader(badHTMLText));
  }   
}   
Run Code Online (Sandbox Code Playgroud)

在这一点上,逻辑method是如此简单,它不值得测试,并且逻辑输入methodForTest很容易访问,你可以大量测试它.

  • +1用于不模拟文件并将逻辑拆分为具有不同关注点的不同对象.**同样在更一般的方式中,根本不是一个你不拥有的模拟类型也不是一个好主意.**所以我在改写杰夫所说的,但写一个**集成测试**将断言代码这将打开和/或写入文件并提供您自己的类型或`Reader` /`Writer`并为处理内容的代码编写**单元测试**,当然您不必模拟`Reader` /`Writer`,但在现有的实现上使用或断言内容,如`StringReader` /`StringWriter`. (9认同)

Tia*_* Na 5

模拟 I/O 调用的一种方法(对于 Java 7,它将是 NIO final class java.nio.file.Files)是将所需的调用包装在您自己的类中并模拟它:

public class FileHelper {

    public Path createDirectory(String directoryName) throws IOException {
        return Files.createDirectory(Paths.get(directoryName));
    }

    public boolean exists(String name) throws IOException {
        return Files.exists(Paths.get(name), LinkOption.NOFOLLOW_LINKS);
    }

}
Run Code Online (Sandbox Code Playgroud)

业务逻辑位于ImageManager

FileHelper fileHelperMock = Mockito.mock(new FileHelper());
ImageManager imageManager = new ImageManagerImpl(fileHelperMock);
Run Code Online (Sandbox Code Playgroud)

该测试将验证createDirectory()对模拟方法的调用:

imageManager.save("directory");
Mockito.verify(fileHelperMock).createDirectory("directory");
Run Code Online (Sandbox Code Playgroud)

我会在测试驱动开发期间使用这种方法,我不想用真正的文件管理来污染测试(例如,在每个单元测试的 finally 块中删除创建的目录/文件)。

然后我将进行验收测试,涵盖每个用例和真实的文件处理。