JUnit Shortcomings I

A few days back I wrote a test that used the filesystem. In order to keep my test independant from any particular file
layout I usually do something like this:

public class SomeFileSystemTest {
    @Test
    public void performTest() throws IOException {
         doStuff(tempDir);
         ...
    }
 
    private File tempDir;
 
 
    @After
    public void deleteTempDir() throws IOException {
        FileUtils.deleteDirectory(tempDir);
    }
 
    @Before
    public  void createTempDir() throws Exception {
        tempDir = File.createTempFile("temp", "SomeFileSystemTest");
        tempDir.delete();
        tempDir.mkdirs();
    }
}

This seems to be the JUnit 4 way of doing things. So today I got back to this test, because I wanted to reuse the temp
directory bit in a different test. So I am wondering if there is any way to reuse this bit other than pulling it into
a shared super class (how a testing framework is promoting bad design).

But how would I like to do this (Christmas-driven-development)?

The functionality for providing a resource and tearing it down again should be encapsulated! So how about this:

public class TempDirFixture implements Fixture {
    final private File tempDir;
 
    public TempDirFixture() throws Exception {
        tempDir = File.createTempFile("temp", "SomeFileSystemTest");
        tempDir.delete();
        tempDir.mkdirs();
    }
 
 
    @Override
    public void tearDown() throws IOException {
        FileUtils.deleteDirectory(tempDir);
    }
 
    public File getTempDir() {
        return tempDir;
    }
}

All I want to do in my test case is to specify, that I want to use a TempDirFixture.
The well adjusted java developers way of doing this is by using a constructor parameter. So the test case would become:

public class SomeFileSystemTest {
    final TempDirFixuture fixture;
 
    public SomeFileSystemTest(TempDirFixuture fixture){
        this.fixture = fixture;
    }
 
    @Test
    public void performTest() throws IOException {
         doStuff(fixture.getTempDir());
         ...
    }
}

Then the test runner would be responsible for newing a TempDirFixture up and tearing it down later.
So the test runner becomes a bit of a mini DI-framework. The dependencies might be injected on the method rather than
the object level. Like this:

public class SomeFileSystemTest {
 
    @Test
    public void performTest(TempDirFixuture fixture) throws IOException {
         doStuff(fixture.getTempDir());
         ...
    }
}

While I am calling for a new feature I am willing to give up the old @before and @after annotations,
because they are so imperative and not what I want to express. Obviously one might also think about the scope of these
Fixtures, but that’s the topic of another blogpost.


Posted

in

by

Tags:

Comments

4 responses to “JUnit Shortcomings I”

  1. Jason Avatar
    Jason

    We implemented this in-house a while back. We looked for any fields in the test of type ‘TestFixture’, and ran through the setUp() and tearDown() methods in the correct order.

    These days, I’d probably make this explicit with a @TestFixture annotation on the field.

    With JUnit 4, you could use the @RunWith annotation to add this easily. The only problem is that it is not easy to compose custom TestRunners.

    One interesting application of this was creating a TestFixture we called the TestFirewaller. It ensured that JMS queues were between functional tests, and helped catch hard to diagnose failures in a test suite.

  2. Shane Avatar

    Hi,

    Regarding testing with file system, I thought you might be interested in an open source project I have (http://cotta.sourceforge.net), which allows you to create a file system in memory by go through the Cotta classes.

    As to the fixture you mentioned, I have started something similar while testing this project but couldn’t think of a good direction to go because Cotta is such a small library. It would be great if you can provide some feedback or even help shaping it.

    I still went with the super class design so here is that class. The annotation @Ftp on it triggers a one-time fixture set up that starts an FTP server. When all the test class with @Ftp finish, it will trigger a one-time tear down. The field annotated with @ForFixture are the ones that the set up code will set so that the test class can use it.

    http://github.com/wolfdancer/cotta/tree/master/ftp/behaviour/src/net/sf/cotta/ftp/FtpTestBase.java

    Cheers
    Shane

  3. […] an earlier post I did describe a possibly better way of handling fixuture tear down in […]

  4. szczepiq Avatar
    szczepiq

    Latest JUnit comes with @Rules (why on earth they have called it Rules? 🙂 feature: http://www.infoq.com/news/2009/07/junit-4.7-rules

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.