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.
Leave a Reply