0

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

cobby
  • 484
  • 3
  • 18

2 Answers2

4

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{}

Community
  • 1
  • 1
Federico Piazza
  • 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
0

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.

bpgergo
  • 15,669
  • 5
  • 44
  • 68