Writing your own JUnit Rule

Niklas Baudy
2 min readApr 14, 2018

--

A JUnit Rule can be used to do some work around the execution of a test.

One example would be to set up something before a test is running and then after it ran tearing something down.

This is actually quite simple to do with JUnit itself.

public class YourTest {
@Before public void setUp() {
// Do something before exampleTest starts.
}
@Test public void exampleTest() {
// Your normal test.
}
@After public void tearDown() {
// Do something after exampleTest finished.
}
}

Now imagine you want to connect to a database during setUp and then close the connection in tearDown. If you want to use that database in multiple files you don’t want to copy paste that code in every file.

TestRule

Let’s look at a quick example of a custom TestRule.

public final class DatabaseRule implements TestRule {
public Database database;

@Override public Statement apply(final Statement base,
final Description description) {
return new Statement() {
@Override public void evaluate() throws Throwable {
database = new SqlDatabase();
try {
base.evaluate(); // This will run the test.
} finally {
database.close();
}
}
};
}
}

Now you just need to add it in your test file.

@Rule public final DatabaseRule databaseRule = new DatabaseRule();

While it seems trivial for this example the amount of set up and tearing down can expand pretty quickly and it’s best to have everything isolated in one place.

TestWatcher

The above rule can be simplified even more by using TestWatcher.

public final class DatabaseRule extends TestWatcher {
public Database database;

@Override protected void starting(Description description) {
database = new SqlDatabase();
}

@Override protected void finished(Description description) {
database.close();
}
}

Locale Example

I needed to control the Locale for a test. Hence I wrote this little rule:

/** JUnit rule for taking control over the Locale. */
public final class DefaultLocaleRule implements TestRule {
final Locale preference;

/**
* Creates the rule and will restore the default locale
* for each test.
*/
public DefaultLocaleRule() {
preference = null;
}

/**
* Creates the rule and will set the preferred locale
* for each test.
*/
public DefaultLocaleRule(final Locale preference) {
this.preference = preference;
}

@Override public Statement apply(final Statement base,
final Description description) {
return new Statement() {
@Override public void evaluate() throws Throwable {
final Locale defaultLocale = Locale.getDefault();

try {
if (preference != null) {
Locale.setDefault(preference);
}

base.evaluate();
} finally {
Locale.setDefault(defaultLocale);
}
}
};
}
}

Now I can easily use it and know for a fact that I won’t assume any default locale on any system and hence will get green tests on every build on every machine.

Conclusion

I hope this shines some light into how to write your first JUnit Rule.

You can use the above rule and some more right now by using my open source JUnit rules library that also has a rule for controlling the Timezone.

testImplementation 'com.vanniktech:junit4-rules:0.2.0'

Please — if you have any — share your JUnit rules and lets all make use of them.

--

--