Search code examples
javatestingjunitclassloaderbinaryfiles

Wrong content of binary test resources when using ClassLoader InputStream


I have a binary file in test resources src/test/resources/file.bin:

$ ls -la src/test/resources

-rw-r--r-- 1 g4s8 g4s8 5125 Apr 30 19:53 file.bin

I'm using it for tests to verify some class. Before testing, I need to copy the content to the file-system, I'm using Thread.currentThread().getContextClassLoader() to read the data:

@Test
public void readsContent(@TempDir final Path tmp) throws Exception {
    final ClassLoader clo = Thread.currentThread().getContextClassLoader();
    final Path file = Files.createFile(tmp.resolve("file.bin"));
    try (
        final InputStream res = new BufferedInputStream(clo.getResourceAsStream("file.bin"));
        final OutputStream out = new BufferedOutputStream(Files.newOutputStream(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE))
    ) {
        byte[] buf = new byte[8192];
        for (int read = res.read(buf); read >= 0; read = res.read(buf)) {
            out.write(buf, 0, read);
        }
    }
    // test code
}

But the content of this file is bigger than expected and it differ from what was in resource file:

$ ls -la /tmp/junit18423574017636618834/

-rw-r--r-- 1 g4s8 g4s8 9350 May  1 12:22 file.bin

The result file is 9350 bytes of size, but source file was 5125. With hex editor I investigated that only first two bytes of these files are the same, all other data is different: enter image description here

What's wrong with my code? Why this file can't be read correctly using standard way via ClassLoader?


Solution

  • It was caused by enabled filtering Maven option inherited from parent pom.xml, it seems Maven managed to find and replace some patterns in binary file, and IDE uses Maven to prepare test resources:

      <build>
        <resources>
          <resource>
            <directory>${basedir}/src/main/resources</directory>
            <filtering>true</filtering>
          </resource>
        </resources>
        <testResources>
          <testResource>
            <directory>${basedir}/src/test/resources</directory>
            <filtering>true</filtering>
          </testResource>
        </testResources>
      </build>
    

    I've overridden this option in project's pom.xml, and it's working now:

    <build>
      <testResources>
        <testResource>
          <directory>${basedir}/src/test/resources</directory>
          <filtering>false</filtering>
        </testResource>
      </testResources>
    </build>