Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

execute some code before any junit test will run

Tags:

java

junit

I have a lot of unit tests files that basically execute the same @BeforeClass.

They start jetty web server, add some system properties.

So I'm wondering, is it possible to execute this only once, before unit test will be run?

like image 472
skatkov Avatar asked Oct 19 '11 19:10

skatkov


People also ask

How do you use before in JUnit?

The @Before annotation is used when different test cases share the same logic. The method with the @Before annotation always runs before the execution of each test case. This annotation is commonly used to develop necessary preconditions for each @Test method.

Will execute the method once before the start of all tests?

It is possible to run a method only once for the entire test class before any of the tests are executed, and prior to any @Before method(s). “Once only setup” are useful for starting servers, opening communications, etc. It's time-consuming to close and re-open resources for each test.

Does @after run after every test?

Create Test fixture before each test.  @Before - method that is run before every test case. setUp( ) is the traditional name.  @After - method that is run after every test case.


3 Answers

You could use the @RunWith annotation:

@RunWith(JettyRunner.class)
public class MyAwesomeTest {
    @Test
    //...
}

And implement a new Runner

public class JettyRunner extends BlockJUnit4ClassRunner {
    private static boolean initialized = false;

    public JettyRunner(Class<?> klass) throws InitializationError {
        super(klass);

        synchronized (JettyRunner.class) {
            if (!initialized) {
                System.out.println("Let's run jetty...");
                initialized = true;
            }
        }
    }
}

I'm not sure if the synchronized block is really needed, just threw it in for good measure...

like image 124
Matt Avatar answered Oct 06 '22 00:10

Matt


Maybe using a static initializer will do? Although it's not a very good idea to initialize some fields only once when running unit tests since some of the tests may drive the fields to an illegal state which will impede the running of the other tests.

like image 30
asenovm Avatar answered Oct 05 '22 22:10

asenovm


In addition to @Matt's answer about creating your own Runner (which I thought was the best approach) (see the answer here), I also created an additional JUnit test that validates that all of my tests use my Runner (in case one of my developers forgets):

PS: Note this depends on OpenPOJO.

@Test
public void ensureAllTestsUseEdgeRunner() {
    for (PojoClass pojoClass : PojoClassFactory.getPojoClassesRecursively("your.base.package", null)) {
        boolean hasTests = false;
        for (PojoMethod pojoMethod : pojoClass.getPojoMethods()) {
            if (hasTests = pojoMethod.getAnnotation(Test.class) != null) {
                break;
            }
            if (hasTests = pojoMethod.getAnnotation(BeforeClass.class) != null) {
                break;
            }
            if (hasTests = pojoMethod.getAnnotation(Before.class) != null) {
                break;
            }
            if (hasTests = pojoMethod.getAnnotation(AfterClass.class) != null) {
                break;
            }
            if (hasTests = pojoMethod.getAnnotation(After.class) != null) {
                break;
            }
        }
        if (hasTests) {
            PojoClass superClass = pojoClass;
            boolean hasRunWith = false;
            while (superClass != null) {
                // ensure it has the RunWith(EdgeJUnitRunner.class) annotation
                RunWith runWithAnnotation = superClass.getAnnotation(RunWith.class);
                if (runWithAnnotation != null && runWithAnnotation.value() == EdgeJUnitRunner.class) {
                    hasRunWith = true;
                    break;
                }
                superClass = superClass.getSuperClass();
            }

            if (!hasRunWith) {
                throw new RuntimeException(pojoClass.getClazz().getName() + " should be annotated with @RunWith(EdgeRunner.class)");
            }
        }
    }
}
like image 35
Mauricio Morales Avatar answered Oct 06 '22 00:10

Mauricio Morales