ChatGPT解决这个技术问题 Extra ChatGPT

如何将文本文件资源读入 Java 单元测试?

我有一个需要使用位于 src/test/resources/abc.xml 中的 XML 文件的单元测试。将文件内容放入 String 的最简单方法是什么?

@Nikita,尽管我的回答将投票结束,但这些问题没有提到 getResourceAsStream(),我认为这是解决 OP 问题的正确方法。
@kirk,getResourceAsStream 将文件缓存在类加载器中。那是不必要的。
@Thorbjørn,您的参考资料在哪里?无论如何,它肯定是方便和便携的,这实际上可能是必要的。
这个问题不应该被关闭。提供的“重复”不回答如何读取资源文件,而是一般的文件。问题是如何引用该资源文件

y
yegor256

多亏了Apache Commons,我终于找到了一个巧妙的解决方案:

package com.example;
import org.apache.commons.io.IOUtils;
public class FooTest {
  @Test 
  public void shouldWork() throws Exception {
    String xml = IOUtils.toString(
      this.getClass().getResourceAsStream("abc.xml"),
      "UTF-8"
    );
  }
}

完美运行。文件 src/test/resources/com/example/abc.xml 已加载(我正在使用 Maven)。

如果您将 "abc.xml" 替换为 "/foo/test.xml",则会加载此资源:src/test/resources/foo/test.xml

您还可以使用 Cactoos

package com.example;
import org.cactoos.io.ResourceOf;
import org.cactoos.io.TextOf;
public class FooTest {
  @Test 
  public void shouldWork() throws Exception {
    String xml = new TextOf(
      new ResourceOf("/com/example/abc.xml") // absolute path always!
    ).asString();
  }
}

可以在没有外部库依赖的情况下简单地做到这一点。
yegor256 因为它是一个单元测试关闭资源特别重要。 “单元”测试应该是快速且自包含的,在测试运行期间可能保持资源开放,这意味着您的测试充其量是运行速度较慢,最坏的情况是以难以诊断的方式失败。
一样紧凑,但正确关闭了输入流:IOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8")
嘿 @yegor256,不是 IOUtils.toString 静态方法吗?根据您众所周知的 static 不喜欢,您现在将如何解决它?
这仅在文件位于同一包中时才有效。如果它们不在同一个包中怎么办
a
akash

切中要害:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());

在使用 junit 测试并希望通过将 xls 文件加载到 byte[] 表单来设置测试时为我工作。
OP 询问“将文件内容转换为字符串的最简单方法是什么?”如果直接回答这个问题,这个答案会更好。
getClass().getClassLoader().getResource("test.xml");
文件 file = new File(getClass().getResource("/responses/example.json").getFile());似乎也可以正常工作,没有 getClassLoader()。
如果您的方法是静态的,这将不起作用。
G
GabrielBB

假设文件中的 UTF8 编码 - 如果不是,只需省略“UTF8”参数 & 将在每种情况下使用底层操作系统的默认字符集。

JSE 6 中的快速方法 - 简单且没有 3rd 方库!

import java.io.File;
public class FooTest {
  @Test public void readXMLToString() throws Exception {
        java.net.URL url = MyClass.class.getResource("test/resources/abc.xml");
        //Z means: "The end of the input but for the final terminator, if any"
        String xml = new java.util.Scanner(new File(url.toURI()),"UTF8").useDelimiter("\\Z").next();
  }
}

JSE 7 中的快速方法

public class FooTest {
  @Test public void readXMLToString() throws Exception {
        java.net.URL url = MyClass.class.getResource("test/resources/abc.xml");
        java.nio.file.Path resPath = java.nio.file.Paths.get(url.toURI());
        String xml = new String(java.nio.file.Files.readAllBytes(resPath), "UTF8"); 
  }

自 Java 9 以来的快速方法

new String(getClass().getClassLoader().getResourceAsStream(resourceName).readAllBytes());

不过,它们都不打算用于巨大的文件。


第二个示例不起作用,readAllBytes 似乎不接受 URL ...我让它工作的最接近的是 String xml = new String(java.nio.file.Files.readAllBytes(Paths.get(url.toURI())), "UTF8");
它确实有效 - 需要一个 Path 类型的参数。这就是为什么我称它为 resPath。 :)
上面将文件内容直接读入内存中的字符串。因此,例如,如果您有 4GB 的内存,那么介于 1-4GB 之间的文件可能会被归类为“巨大”,因为它会消耗非常大比例的内存资源(页面交换到磁盘,除此之外)。对于大文件,最好流式传输 - 分块读取,而不是一次全部读取。
java7版本完美,tip:使用StandardCharsets.UTF_8避免unsupportedEncodingException
你能解释一下为什么你使用 MyClass 而不是 FoTest 以及你什么时候想使用哪个类?
K
Kirk Woll

首先确保将 abc.xml 复制到您的输出目录。那么你应该使用 getResourceAsStream()

InputStream inputStream = 
    Thread.currentThread().getContextClassLoader().getResourceAsStream("test/resources/abc.xml");

获得 InputStream 后,只需将其转换为字符串。此资源详细说明:http://www.kodejava.org/examples/266.html。但是,我将摘录相关代码:

public String convertStreamToString(InputStream is) throws IOException {
    if (is != null) {
        Writer writer = new StringWriter();

        char[] buffer = new char[1024];
        try {
            Reader reader = new BufferedReader(
                    new InputStreamReader(is, "UTF-8"));
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
        } finally {
            is.close();
        }
        return writer.toString();
    } else {        
        return "";
    }
}

your output directory 是什么?
@Vincenzo,通常是“类”,尽管可能是“bin”。即无论你在哪里编译你的类。大多数 IDE 已经将资源文件(例如 xml 文件)复制到该目录,因此您可能应该快速查看它是否已经存在。
在您的情况下,看起来代码太多了。我最好使用一些 apache.commons.io.* 类来读取文件,以及 java.lang.Class.getResource()。你怎么看?
一个很好的测试方法是,如果您将测试用例写入带有 testKey = value 的“.properties”文件,然后您可以直接加载 InputStream。示例:属性 properties = new Properties();属性.load(inputStream);字符串 testCase = properties.getProperty("testKey");
如何将 abc.xml 复制到输出目录? @KirkWoll
D
Datageek

使用谷歌番石榴:

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws Exception {
        try {
            return Resources.toString(Resources.getResource(fileName), charset);
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
}

例子:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)

G
Guido Celada

您可以尝试这样做:

String myResource = IOUtils.toString(this.getClass().getResourceAsStream("yourfile.xml")).replace("\n","");

为什么要剥离新线?
@zudduz 对不起,我不记得了,这是 2 年前的事了
IOUtils.toString toString(stream) 也被弃用了。需要在 IOUtils.toString 中传递一个 Charsets toString(stream, Charsets.UTF_8) (import com.google.common.base.Charsets;)
实际上为了避免弃用,它应该是: String myResource = IOUtils.toString(this.getClass().getResourceAsStream("yourfile.xml"), StandardCharsets.UTF_8).replace("\n","");
i
ikryvorotenko

这是我用来获取带有文本的文本文件的内容。我使用了 commons 的 IOUtils 和 guava 的 Resources。

public static String getString(String path) throws IOException {
    try (InputStream stream = Resources.getResource(path).openStream()) {
        return IOUtils.toString(stream);
    }
}

A
Ahmed Ashour

您可以使用 Junit Rule 为您的测试创建这个临时文件夹:

@Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
File file = temporaryFolder.newFile(".src/test/resources/abc.xml");

K
KhogaEslam

好的,对于JAVA 8,经过大量调试我发现两者之间存在差异

URL tenantPathURI = getClass().getResource("/test_directory/test_file.zip");

URL tenantPathURI = getClass().getResource("test_directory/test_file.zip");

是的,路径开头的 / 没有它我得到 null

test_directory 位于 test 目录下。


d
djangofan

使用 Commons.IO,此方法可以从实例方法或静态方法中工作:

public static String loadTestFile(String fileName) {
    File file = FileUtils.getFile("src", "test", "resources", fileName);
    try {
        return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
    } catch (IOException e) {
        log.error("Error loading test file: " + fileName, e);
        return StringUtils.EMPTY;
    }
}