@BeforeClass doesn't really make sense to me. Everything in that method will be executed before all test cases. But couldn't we write that simply at the beginning of the test class and have the same effect?
-
3What do you mean by "at the beginning of the class"? – Tunaki Oct 02 '15 at 16:49
2 Answers
You can "technically" do the same, however you have differents behaviors behind the scenes, since @BeforeClass
is handled by JUnit whilst standard java code in statics blocks or class initializers are handled by the JVM.
You can "compare" @BeforeClass
with jvm static blocks but @BeforeClass
is called by JUnit while statics blocks are called by the JVM.
In case you have a failure in your initializers (either JUnit or JVM), you will have a different errors.
Handled by JUnit
public class TestCase {
static private int number;
@BeforeClass
public static void init(){
number = 1/0; // Makes a failure
}
}
// THROWS THIS STACK TRACE
java.lang.ArithmeticException: / by zero
at com.creditsesame.integration.util.GenericUtilsTest.test(GenericUtilsTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
Maven Test goal output
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.005 sec <<< FAILURE! - in com.fede.TestCase
com.fede.TestCase Time elapsed: 0.005 sec <<< ERROR!
java.lang.ArithmeticException: / by zero
at com.fede.TestCase.init(TestCase.java:24)
Results :
Tests in error:
TestCase.init:24 Arithmetic / by zero
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 13.864 s
[INFO] Finished at: 2015-10-02T11:35:32-06:00
[INFO] Final Memory: 33M/448M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project integration: There are test failures.
[ERROR]
[ERROR] Please refer to E:\Project\workspace\fede\target\surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
Handled by JVM
public class TestCase {
static int i=1/0; // Makes a failure
@BeforeClass
public static void init(){
number = 1/0;
}
}
// THROWS THIS STACK TRACE
java.lang.ExceptionInInitializerError
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
Caused by: java.lang.ArithmeticException: / by zero
Maven Test goal output
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.008 sec - in com.fede.TestCase
Results :
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:09 min
[INFO] Finished at: 2015-10-02T11:34:02-06:00
[INFO] Final Memory: 28M/607M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project integration: ExecutionException: java.lang.RuntimeException: There was an error in the forked process
[ERROR] java.lang.ExceptionInInitializerError
[ERROR] at java.lang.Class.forName0(Native Method)
[ERROR] at java.lang.Class.forName(Class.java:191)
[ERROR] at org.junit.runner.Description.getTestClass(Description.java:206)
[ERROR] at org.apache.maven.surefire.common.junit48.FilterFactory$GroupMatcherCategoryFilter.shouldRun(FilterFactory.java:281)
[ERROR] at org.apache.maven.surefire.common.junit48.FilterFactory$GroupMatcherCategoryFilter.shouldRun(FilterFactory.java:227)
[ERROR] at org.junit.runners.ParentRunner.shouldRun(ParentRunner.java:299)
[ERROR] at org.junit.runners.ParentRunner.filter(ParentRunner.java:254)
[ERROR] at org.junit.runner.manipulation.Filter.apply(Filter.java:79)
[ERROR] at org.apache.maven.surefire.junitcore.JUnitCoreWrapper$FilteringRequest.<init>(JUnitCoreWrapper.java:139)
[ERROR] at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.createRequestAndRun(JUnitCoreWrapper.java:100)
[ERROR] at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.executeEager(JUnitCoreWrapper.java:78)
[ERROR] at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.execute(JUnitCoreWrapper.java:54)
[ERROR] at org.apache.maven.surefire.junitcore.JUnitCoreProvider.invoke(JUnitCoreProvider.java:144)
[ERROR] at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
[ERROR] at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
[ERROR] at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
[ERROR] Caused by: java.lang.ArithmeticException: / by zero
[ERROR] at com.creditsesame.integration.util.GenericUtilsTest.<clinit>(GenericUtilsTest.java:22)
[ERROR] ... 16 more
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
JUnit comments
When you annotate with @BeforeClass
the method is executed only once, this is useful for initializations/loggings you want to happen just once. You can check a very useful link explaining this here. The difference with @Before
is that it is being executed after each test case.
Take a look at this example:
package com.javacodegeeks.junit;
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.*;
public class JunitTestExample {
private ArrayList testList;
@BeforeClass
public static void onceExecutedBeforeAll() {
System.out.println("@BeforeClass: onceExecutedBeforeAll");
}
@Before
public void executedBeforeEach() {
testList = new ArrayList();
System.out.println("@Before: executedBeforeEach");
}
@Test
public void EmptyCollection() {
assertTrue(testList.isEmpty());
System.out.println("@Test: EmptyArrayList");
}
@Test
public void OneItemCollection() {
testList.add("oneItem");
assertEquals(1, testList.size());
System.out.println("@Test: OneItemArrayList");
}
}
The output will be:
@BeforeClass: onceExecutedBeforeAll
@Before: executedBeforeEach
@Test: EmptyArrayList
@Before: executedBeforeEach
@Test: OneItemArrayList
You can find a detailed explanation in @BeforeClass vs static{}

- 1
- 1

- 30,085
- 15
- 87
- 123
-
Yes, but you could simply write the first System.out without the @BeforeClass and have the same output? – cobby Oct 02 '15 at 17:02
-
@cobby "yes" and "no". `@BeforeClass` is handled by JUnit and it's a better choice to cover your testing behavior, since using standard code can mess up your testing. Think of it as delegating your code, if you are writing a unit test with JUnit then delegate the unit testing to it instead of mixing jvm with JUnit. – Federico Piazza Oct 02 '15 at 17:07
I'm not sure what you mean by 'in the beginning of the class', but the @BeforeClass method can be used to initialize a group of test case.
Imagine there is some kind of initialization that is time consuming and it is the same for a lot of test cases. You do not want to repeat that many times because that will make the whole testing running too long.

- 15,669
- 5
- 44
- 68