Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a private method inside every JUnit before any test steps

Tags:

java

junit

I want to know if there is any technical difference between the following, when writing JUnit tests:

Option 1: Define a setup method, i.e annotated with @Before, to initialize test fixture state before any @Test method is run.

Option 2: Define a private method - just a plain old private method without any annotation - that does the same initialization, and make the first line of every @Test method a call to this method. (Ignore the possibility of someone forgetting to call the method in every test. I am looking for technical differences, not human factors)

Example of Option 2:

public class MyTest {

    private void runSetupLogic() {
        // whatever @Before method would have done
    }

    @Test
    public void testMethod1() {
        runSetupLogic();
        // test logic
    }

    @Test
    public void testMethod2() {
        runSetupLogic();
        // test logic
    }
}
like image 749
Ajoy Bhatia Avatar asked Dec 08 '25 20:12

Ajoy Bhatia


1 Answers

They are not really exactly the same, but for all intents and purposes either way should be fine. However, if you are interested in the technical analysis then my shaky understanding of the current JUnit 4 code on Github follows:

Here is what seems to be the actual code being ran when you use @Before using the default JUnit 4 runner src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java:

/**
 * Returns a {@link Statement}: run all non-overridden {@code @Before}
 * methods on this class and superclasses before running {@code next}; if
 * any throws an Exception, stop execution and pass the exception on.
 */
protected Statement withBefores(FrameworkMethod method, Object target,
        Statement statement) {
    List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
            Before.class);
    return befores.isEmpty() ? statement : new RunBefores(statement,
            befores, target);
}

The above calls RunBefores in src/main/java/org/junit/internal/runners/statements/RunBefores.java:

public class RunBefores extends Statement {
    private final Statement next;

    private final Object target;

    private final List<FrameworkMethod> befores;

    public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
        this.next = next;
        this.befores = befores;
        this.target = target;
    }

    @Override
    public void evaluate() throws Throwable {
        for (FrameworkMethod before : befores) {
            before.invokeExplosively(target);
        }
        next.evaluate();
    }

The invokeExplosively method definition is in src/main/java/org/junit/runners/model/FrameworkMethod.java:

public Object invokeExplosively(final Object target, final Object... params)
        throws Throwable {
    return new ReflectiveCallable() {
        @Override
        protected Object runReflectiveCall() throws Throwable {
            return method.invoke(target, params);
        }
    }.run();
}

which seems to use reflection to invoke the methods annotated with @Before.

Anyway, hope this answer is somewhat correct, but I'm not sure. If anyone has any corrections I can edit them in from the comments. By the way, for reference here is the javadoc for the @Before annotation: http://junit.org/javadoc/latest/org/junit/Before.html

like image 185
Christian Wilkie Avatar answered Dec 11 '25 08:12

Christian Wilkie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!