Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中模拟文件IO?_Java_File_Io - Fatal编程技术网

如何在Java中模拟文件IO?

如何在Java中模拟文件IO?,java,file,io,Java,File,Io,如何创建类MockFile模仿java.io.Filew.r.t.文件读写?我在任何地方都使用自己的方法,而不是newfileinputstream(..)和newfileoutputstream(..),因此这部分没有问题(我总是委托给适当的流)。非trivila部分是myMockFileInputStream和MockFileOutputStream在更复杂的情况下的实现 没有问题,当我第一次写入文件然后读取它时,我可以简单地使用ByteArrayOutputStream等等。这很简单,但在

如何创建类
MockFile
模仿
java.io.File
w.r.t.文件读写?我在任何地方都使用自己的方法,而不是
newfileinputstream(..)
newfileoutputstream(..)
,因此这部分没有问题(我总是委托给适当的流)。非trivila部分是my
MockFileInputStream
MockFileOutputStream
在更复杂的情况下的实现


没有问题,当我第一次写入文件然后读取它时,我可以简单地使用
ByteArrayOutputStream
等等。这很简单,但在交替读写的情况下,它无法工作。有没有比用TearrayOutputStream编写自己版本的
更好的主意?

我会使用一个真实的文件和一个真实的
文件输入流
文件输出流
。否则,您只是在练习测试代码:实际上毫无意义。

我创建了一个“WordCounter”类来计算文件中的单词。但是,我想对我的代码进行单元测试,单元测试不应该触及文件系统

因此,通过将实际的文件IO(FileReader)重构为它自己的方法(让我们面对现实,标准Java文件IO类可能会工作,因此我们通过测试它们不会获得太多收益),我们可以单独测试我们的字计数逻辑

import static org.junit.Assert.assertEquals;

import java.io.*;

import org.junit.Before;
import org.junit.Test;

public class WordCounterTest {

    public static class WordCounter {

        public int getWordCount(final File file) throws FileNotFoundException {
            return getWordCount(new BufferedReader(new FileReader(file)));
        }

        public int getWordCount(final BufferedReader reader) {
            int wordCount = 0;
            try {
                String line;
                while ((line = reader.readLine()) != null) {
                    wordCount += line.trim().split(" ").length;
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return wordCount;
        }
    }

    private static String TEST_CONTENT = "Neque porro quisquam est qui dolorem\n"
            + " ipsum quia dolor sit amet, consectetur, adipisci velit...";

    private WordCounter wordCounter;

    @Before
    public void setUp() {
        wordCounter = new WordCounter();
    }

    @Test
    public void ensureExpectedWordCountIsReturned() {
        assertEquals(14, wordCounter.getWordCount(new BufferedReader(new StringReader(TEST_CONTENT))));
    }
}
编辑:我应该注意,如果您的测试与代码共享同一个包,则可以降低代码的可见性

public int getWordCount(final BufferedReader reader)
方法,以便您的公共API仅公开

public int getWordCount(final File file)

为什么您试图通过文件在同一系统中的组件之间交换数据?为什么不使用一个临时文件来创建一个模拟文件呢?你可能会找到你的答案[here][1][1]:@Peter Lawrey我不是在尝试交换数据,我是在尝试模仿程序的工作方式(为了一种集成测试)。使用临时文件非常简单,但速度不是很快,特别是当我只需要几个字节时。通过临时文件传递几个字节需要大约10毫秒。如果这是性能问题,为什么要使用文件?顺便说一句,如果您可以在unix上使用tmpfs,例如/tmp/deleteme.dat,这将占用一小部分时间,因为它实际上不会写入磁盘,而是写入内存。@Peter Lawrey“如果这是性能问题,为什么要使用文件?”在实际运行中,当这些数据不时被写入或读取时,这并没有问题,但在测试中情况更糟。但我同意这可能不值得这么麻烦,所以我只使用临时文件,至少现在是这样。@EJP这就像“交付给客户,看着他发疯。否则你只是在练习测试代码,真的毫无意义。”,不是吗?@maaartinus你必须解释一下,因为我不明白。测试的目的是测试真实代码,而不是测试代码。测试测试代码是一种无限的回归,它实际上并没有达到向客户交付工作代码的目标。@EJP大多数测试实际上是由真实代码和测试代码(模拟)的混合体组成的,对吗?我们希望通过这种方式捕获真实代码中的错误,对吗?模拟有助于隔离问题和/或更快地运行测试(无慢速操作)或降低成本(无真正的银行操作)或重复测试(无真正的核导弹发射),对吗?那么,模拟文件系统有什么错呢?模拟文件系统没有什么错。EJP的意思(我认为)是,不断地对简单的事情使用mock,最终导致大量的mock,以至于您不再测试真正的代码。这本质上是一个滑坡。也许使用内存文件系统(正如@peter lawrey所建议的)是一个完美的折衷方案。您可以测试与文件系统的真实交互,而不是假设您正确使用了API。关于这个的详细信息,请参见。@maaartinus它的错误在于它毫无意义。它没有你提到的任何风险,比如引发世界末日或将国债增加三倍,OP特别提到他想测试交错,这在真正的文件系统中已经足够难了,更不用说只为这个目的编写的东西了。恐怕你错过了我问题的第二段。。。你所做的只适合阅读或写作,但我需要测试一个组合。这不是一个单元测试,而是对程序不同部分合作的测试。