3

The following JUnit 4 test works fine under Linux and Windows:

public class TmpFileTest {

    @Rule
    public TemporaryFolder tmp = new TemporaryFolder();

    @Test
    public void test() throws Exception {
        File tmpFile = tmp.newFile();
        Assert.assertEquals(tmpFile, tmpFile.getCanonicalFile());
    }

}

But the assertion fails on Mac (tested with Sierra 10.12.4):

java.lang.AssertionError: 
Expected :/var/folders/q4/rj3wqzms2fdcqlxgdzb3l5hc0000gn/T/junit1451860092188597816/junit1906079638039608483.tmp
Actual   :/private/var/folders/q4/rj3wqzms2fdcqlxgdzb3l5hc0000gn/T/junit1451860092188597816/junit1906079638039608483.tmp

var is a symlink that points to private/var, which is resolved via File#getCanonicalFile()—this is the difference.

Is there a way to fix this? This causes a bunch of test failures on my machine.

beatngu13
  • 7,201
  • 6
  • 37
  • 66
  • Why do you need a file’s path and its canonical path to be the same? Why even test for that? – VGR May 05 '17 at 17:01
  • @VGR the affected tests are a bit more complicated and the creator probably wasn't aware of that problem as it only occurs on Mac. Our CI server currently runs on Linux exclusively, hence, the tests pass there as well. I know this should be adapted in the medium term, but I'm looking for a quick solution (if there is one). – beatngu13 May 05 '17 at 19:29

2 Answers2

3

I imagine you still need to verify that two paths are the same.

So, instead of trying to work around how getCanonicalFile() works (it resolves symlinks, no way around that), you can embrace it, and in the final test you can use getCanonicalFile() on both ends.

File expectedFile = ...
File actualFile = ...
assertEquals(expectedFile.getCanonicalFile(), tmpFile.getCanonicalFile());

That, or:

java.nio.file.Files.isSameFile(expectedFile.toPath(), actualFile.toPath())
Hugues M.
  • 19,846
  • 6
  • 37
  • 65
2

As pointed out by Hugues Moreau's answer, the best thing is to simply fix the tests rather than working around the given behavior.

However, a quick hack can make the tests pass. By using the alternative TemporaryFolder constructor (available as of JUnit 4.11; see this answer for prior versions), one can set the parent folder:

@Rule
public TemporaryFolder tmp = new TemporaryFolder(System.getProperty("os.name").startsWith("Mac")
        ? new File("/private/" + System.getProperty("java.io.tmpdir"))
        : new File(System.getProperty("java.io.tmpdir")));

Using SystemUtils#IS_OS_MAC from Apache Commons Lang makes this a bit more readable.

Community
  • 1
  • 1
beatngu13
  • 7,201
  • 6
  • 37
  • 66