@RunWith in junit4

@RunWith is used to specify the Runner to run the unit test. A runner defines how a test method executes usually through reflection mechanism. The default runner in junit4 is BlockJUnit4ClassRunner.

Above image is clipped from the source code of block runner. It’s easy to figure out that why @Ignore annotation can skip a test method.

Runner is an extension point that we can customize how a test function runs. For example, I want to add a @DisplayName annotation to make the test name more meaningful. I can do it as below:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.runner.Description;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class CustomizeTestNameRunner extends BlockJUnit4ClassRunner {

  public CustomizeTestNameRunner(Class<?> klass) throws InitializationError {
    super(klass);
  }

  @Override
  protected Description describeChild(FrameworkMethod method) {
    DisplayName name = method.getAnnotation(DisplayName.class);
    if (name != null) {
      return Description.createTestDescription(getTestClass().getJavaClass(), name.value());
    }
    return super.describeChild(method);
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target({ElementType.METHOD})
  public @interface DisplayName {

    String value();
  }
}
public class AppTest {

  public static int add(int a, int b) {
    return a + b;
  }

  @Test
  @DisplayName("test add two integer")
  public void testAdd() {
    assertEquals(7, add(3, 4));
  }
}

Next time if you see a test is annotated with @RunWith(SomeClass.class). Don’t be surprised. The extra features you don’t see before are fully implemented by the Runner.