Rules in JUnit 4.7

Written on Thursday, July 16th, 2009 at 1:39 pm by David Saff
Filed under Uncategorized.

All,

JUnit 4.7 will include a new mechanism for changing the behavior and
interpretation of test methods.  We are calling this feature Rules
(replacing the earlier name Interceptors).  You can download a
snapshot of this release.  We are planning no new
feature for this version, and once the tagged bugs are resolved, we will issue an
official release candidate, but early feedback is very, very welcome.

There are already rules you’re probably familiar with from way back in
JUnit 4.0:

  • The fundamental rule of JUnit: a test method is executed on a new
    instance of its declaring class.  It passes if and only if it
    completes without throwing an exception.
  • The Before rule: a @Test method is preceded by all @Before methods
    in the same class.
  • The After rule: a @Test method is followed by all @After methods in
    the same class.
  • The timeout= rule: if a @Test annotation has a timeout= property, it
    fails if it does not complete in under the given number of
    milliseconds
  • The expected= rule: if a @Test annotation has an expected= property,
    it passes if it throws an exception of the given class name, and fails
    otherwise.

Starting with 4.7, you can add additional rules to methods in a class
by declaring public fields in the class annotated with @Rule.  For
example, here’s a test that uses the TemporaryFolder rule (”All files
created in the temporary folder during the test are deleted after the
test completes.”):

 public static class HasTempFolder {
   @Rule
   public TemporaryFolder folder= new TemporaryFolder();

   @Test
   public void testUsingTempFolder() throws IOException {
     File createdFile= folder.newFile("myfile.txt");
     File createdFolder= folder.newFolder("subfolder");
     // ...
   }
 }

We’re including implementations of the following Rules:

  • TemporaryFolder: delete temp files after test completion
  • ExternalResource: reliably set up and tear down an arbitrary external resource
  • ErrorCollector: collect multiple assertion failures per test method, and report all at the end
  • Verifier: turn a passing test to failing if an arbitrary condition is not met (all expected mock-object calls made, no ERROR lines in the logs)
  • TestWatchman: Perform an additional task before and after each test (a custom log, for example)
  • TestName: remember the name of each test method, and make it available during the test execution.
  • Timeout: like the timeout= rule, but applies to all methods in a class, and can take a run-time value.
  • ExpectedException: like the expected= rule, but can check exception messages, and other arbitrary assertions.

For more on using these rules, please see the release notes.

In addition, you can implement your own Rules by implementing the
MethodRule interface.  Here’s a Rule that marks all tests as passing,
as long as I’m the one running them:

public class DavidsAlwaysRight implements MethodRule {
       public Statement apply(Statement base, FrameworkMethod method, Object target) {
               if ("saff".equals(System.getenv("USER")))
                       return alwaysSuccess();
               else
                       return base;
       }

       private Statement alwaysSuccess() {
               return new Statement() {
                       @Override
                       public void evaluate() throws Throwable {
                               // do nothing: always success!
                       }
               };
       }
}

While you’re here, don’t forget the T-shirt.

Leave a Reply

You must be logged in to post a comment.