JUnit @Rule not initialized before @BeforeClass

In JUnit, @Rule objects are not initialized before @BeforeClass methods are called (as of the current version 4.8.1.)

Is this by design or a bug?

Both:

  • Rules where not designed to be declared as static, but to be set up and torn down for each @Test method run.
  • The bug is that the code comments inside JUnit indicate this is not legal but the code does not disallow it, like JUnit disallows @BeforeClass methods from not being static.

Why is this an issue?

Here is some context: In a test, we want to configure a server, start it, run tests, shutdown the server and clear any evidence left on disk.

I was hoping this would map to JUnit as follows:

  1. Configure the server: Use a TemporaryFolder Rule to create server configuration files.
  2. Start the server in @BeforeClass using the configuration files.
  3. Run tests in @Test methods
  4. Shutdown the server in @AfterClass
  5. Clear configuration files and anything else the server created there (logs and other temp files) is done automatically by the TemporaryFolder Rule

This test demonstrates the issue:

package test;

import java.io.File;
import java.io.IOException;

import junit.framework.Assert;

import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class TemporaryFolderRuleBeforeClass {
 @Rule
 public static TemporaryFolder testFolder = new TemporaryFolder();

 @BeforeClass
 public static void testInTempFolder() throws IOException {
 File tempFile = testFolder.newFile("file.txt");
 File tempFolder = testFolder.newFolder("folder");
 System.out.println("Test folder: " + testFolder.getRoot());
 // test
 Assert.assertNotNull(testFolder.getRoot());
 }

 @Test
 public void test() {
 // ...
 }
}

If you run the above example, you get an AssertionFailedError:

junit.framework.AssertionFailedError
  at junit.framework.Assert.fail(Assert.java:48)
  at junit.framework.Assert.assertTrue(Assert.java:20)
  at junit.framework.Assert.assertNotNull(Assert.java:218)
  at junit.framework.Assert.assertNotNull(Assert.java:211)
  at test.TemporaryFolderRuleBeforeClass.testInTempFolder(TemporaryFolderRuleBeforeClass.java:23)

Having the TemporaryFolder Rule declared as static is OK as this example test shows:

package test;

import java.io.File;
import java.io.IOException;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class TestTemporaryFolderRuleStatic {
    @Rule
    public static TemporaryFolder testFolder = new TemporaryFolder();

    @Test
    public void testInTempFolder() throws IOException {
        File tempFile = testFolder.newFile("file.txt");
        File tempFolder = testFolder.newFolder("folder");
        System.out.println("Test folder: " + testFolder.getRoot());
        // test
        Assert.assertNotNull(testFolder.getRoot());
    }
}

How can @Rules be used from @BeforeClass?

Calling TemporaryFolder.create() would work only for TemporaryFolder and not Rules in general but would be against the advice of of the Javadoc in the method create()

Unfortunately, there is no solution to this problem but to patch JUnit. For a discussion and proposal for a fix, see this discussion: http://tech.groups.yahoo.com/group/junit/message/22516

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s