@RunWith in junit4

java

@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.

b6b04903-2747-44cd-a3ce-454beac3ba50

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));
  }
}

34b93197-99a6-43c6-8fb0-57c14a75a06d

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.