Reputation: 623
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
}
}
Upvotes: 3
Views: 2485
Reputation: 1008
The benifit comes from reporting.
In your method: runSetupLogic()
when ran from the start of a test, is reported within the test. Not as part of the setup and not as part of the initialization.
If the setup method fails, you get an accurate description of what failed... setup vs testing.
The before method allows you to isolate test failures from setup failures and allows the reporting solution to know as well.
Upvotes: 1
Reputation: 647
I do not believe so.
However, if you were you implement another function, such as tearDown(), that would function essentially as an @After method, I would argue you might as well use them for readability, for the benefit of other collaborators or maybe even yourself.
The upside to using @Before and @After annotations is the that they avoid having to call a method at the beginning of each unit test, designed to save you the extra maintenance. If for some reason you had forgotten to add the call to your setUp() and/or tearDown() method, who knows what could go wrong.
This is, of course, if you need the EXACT SAME setup before each test. If you envision having a completely different setup for different unit tests, than perhaps you should look at the functionality of the class you are testing and ask yourself if perhaps you could modularize more.
Upvotes: 2
Reputation: 3823
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
Upvotes: 2