JUnit: Using External Resources

Many integration test cases need access to external resources like files or databases. Dealing with external resources is always messy because you have to set up state and tear it down later. Since JUnit 4.7, there's a mechanism that makes things a bit more convenient.

Previously when you had to create files in a test case, you had to set up a temporary directory in a @Before method and later delete it in an @After method. But now, JUnit provides a simple AOP-like mechanism called Rules that makes this setup and cleanup work the responsibility of the resource.

This is how it works. You make your resource an attribute of your test class and annotate it with the new @Rule annotation. The resource has to implement the MethodRule interface (or extend ExternalResource, which is more convenient). Your test case just uses the resource and doesn't mind about the rest.

Here's an example for a test case that uses TemporaryFolder to create a file in a temporary directory:

public class SomeTest {

    @Rule
    public TemporaryFolder tmpDir = new TemporaryFolder();

    @Test
    public void testSomething() throws IOException {
        File file = tmpDir.newFile("out");

        // interact with file
    }
}

While the mechanism is great, there's a few things that could be improved.

In Java as in Unix, we talk about directories, not folders. Each time I have to explain "computer stuff" to people from outside the IT world, I curse Microsoft for inventing this stupid term.

It would also be better if TemporaryFolder created the directory only on demand as soon as a test method accesses it. Perhaps this sounds like premature optimization but fastest I/O is still no I/O and test cases should run as fast as possible.

And finally: Is it only me or is @Rule a weird terminology choice? They originally used @Interceptor which is more intuitive since it's how the concept is called in EJB.

Anyway, nitpicking aside, it's still a cool feature that I'm going to use in the future.

social