Understanding JUnit Rules

[Updated: Aug 5, 2017, Created: Jul 13, 2017]

JUnit rules are used to reuse code. This is a better alternative to extending a test class. Using inheritance for code reuse (rather than polymorphism) is considered a bad practice, we should use composition instead (more info). JUnit rule is based on object composition but is more powerful, that's because they can integrate with the tests lifecycle as well.

To have a quick idea what rules are for and how to use them, we will see a simple example of Timeout rule (already defined in JUnit framework). Timeout Rule applies a specified timeout to all test methods in the test class. It is a subclass of TestRule (all rules should be subclass of TestRule). We also need to use @Rule annotation on the rule field instance.

Example

public class MyTestClass {
  @Rule
  public Timeout myTestClassTimeout = new Timeout(250, TimeUnit.MILLISECONDS);

  @Test
  public void testMethod1() throws InterruptedException {
      System.out.println("running testMethod1()");
      Thread.sleep(200);
  }

  @Test
  public void testMethod2() throws InterruptedException {
      System.out.println("running testMethod2()");
      Thread.sleep(300);
  }

  @Test
  public void testMethod3() throws InterruptedException {
      System.out.println("running testMethod3()");
      Thread.sleep(100);
  }
}
mvn -q test -Dtest=MyTestClass

Output

D:\example-projects\junit\timeout-rule-example>mvn -q test -Dtest=MyTestClass
running testMethod1()
running testMethod2()
running testMethod3()
[ERROR] Tests run: 3, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.593 s <<< FAILURE! - in com.logicbig.example.MyTestClass
[ERROR] testMethod2(com.logicbig.example.MyTestClass) Time elapsed: 0.255 s <<< ERROR!
org.junit.runners.model.TestTimedOutException: test timed out after 250 milliseconds
at com.logicbig.example.MyTestClass.testMethod2(MyTestClass.java:22)

[ERROR] Errors:
[ERROR] MyTestClass.testMethod2:22 ยป TestTimedOut test timed out after 250 millisecond...
[ERROR] Tests run: 3, Failures: 0, Errors: 1, Skipped: 0
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.20:test (default-test) on project timeout-rule-example: There are test failures.
[ERROR]
[ERROR] Please refer to D:\example-projects\junit\timeout-rule-example\target\surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date]-jvmRun[N].dump, [date].dumpstream and [date]-jvmRun[N].dumpstream.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Above output does not report 1 test failure, instead it reports a normal exception. Looks like there is a bug in maven JUnit runner.

Running the test class in Intellij, reports 1 test failure.

Example Project

Dependencies and Technologies Used :

  • junit 4.12: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck..
  • JDK 1.8
  • Maven 3.3.9

JUnit Timeout Rule Example Select All Download
  • timeout-rule-example
    • src
      • main
      • test
        • java
          • com
            • logicbig
              • example

See Also