Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit crashes saying method should be static, then crashes saying it shouldn't?

I'm trying to make a simple example test in JUnit that tests two things, then does teardown.

import org.junit.*;

public class TestFoobar {
    @Test
    public void testOneThing() {
        // Code that tests one thing
    }

    @Test
    public void testAnotherThing() {
        // Code that tests another thing
    }

    @AfterClass
    @Test
    public void tearDownClass() throws Exception {
        // Code executed after the last test method 
    }
}

When I try to run this, it crashes saying tearDownClass has to be static:

$ javac TestFoobar.java -cp junit-4.8.2.jar
$ java -cp junit-4.8.2.jar:. org.junit.runner.JUnitCore TestFoobar
JUnit version 4.8.2
.E
Time: 0.01
There was 1 failure:
1) initializationError(TestFoobar)
java.lang.Exception: Method tearDownClass() should be static
    at org.junit.runners.model.FrameworkMethod.validatePublicVoid(FrameworkMethod.java:83)
    at org.junit.runners.model.FrameworkMethod.validatePublicVoidNoArg(FrameworkMethod.java:66)
    at org.junit.runners.ParentRunner.validatePublicVoidNoArgMethods(ParentRunner.java:122)
    at org.junit.runners.ParentRunner.collectInitializationErrors(ParentRunner.java:104)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:119)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:269)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:66)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:58)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:13)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runner.Computer.getRunner(Computer.java:38)
    at org.junit.runner.Computer$1.runnerForClass(Computer.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:93)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:84)
    at org.junit.runners.Suite.<init>(Suite.java:79)
    at org.junit.runner.Computer.getSuite(Computer.java:26)
    at org.junit.runner.Request.classes(Request.java:69)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
    at org.junit.runner.JUnitCore.runMain(JUnitCore.java:98)
    at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:53)
    at org.junit.runner.JUnitCore.main(JUnitCore.java:45)

FAILURES!!!
Tests run: 1,  Failures: 1

So I change tearDownClass to static, but now it says it should not be static:

$ javac TestFoobar.java -cp junit-4.8.2.jar
$ java -cp junit-4.8.2.jar:. org.junit.runner.JUnitCore TestFoobar
JUnit version 4.8.2
.E
Time: 0.01
There was 1 failure:
1) initializationError(TestFoobar)
java.lang.Exception: Method tearDownClass() should not be static
    at org.junit.runners.model.FrameworkMethod.validatePublicVoid(FrameworkMethod.java:83)
    at org.junit.runners.model.FrameworkMethod.validatePublicVoidNoArg(FrameworkMethod.java:66)
    at org.junit.runners.ParentRunner.validatePublicVoidNoArgMethods(ParentRunner.java:122)
    at org.junit.runners.BlockJUnit4ClassRunner.validateTestMethods(BlockJUnit4ClassRunner.java:200)
    at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:174)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:122)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:269)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:66)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:58)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:13)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runner.Computer.getRunner(Computer.java:38)
    at org.junit.runner.Computer$1.runnerForClass(Computer.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:93)
    at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:84)
    at org.junit.runners.Suite.<init>(Suite.java:79)
    at org.junit.runner.Computer.getSuite(Computer.java:26)
    at org.junit.runner.Request.classes(Request.java:69)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
    at org.junit.runner.JUnitCore.runMain(JUnitCore.java:98)
    at org.junit.runner.JUnitCore.runMainAndExit(JUnitCore.java:53)
    at org.junit.runner.JUnitCore.main(JUnitCore.java:45)

FAILURES!!!
Tests run: 1,  Failures: 1

Why?

like image 525
Dog Avatar asked Jan 28 '14 17:01

Dog


2 Answers

You have extraneous annotations. it should be:

@AfterClass
public static void tearDownClass() throws Exception {
    // Code executed after the last test method 
}

That method itself should be static in order to perform the teardown, and itself should not be a @Test.

like image 191
nanofarad Avatar answered Nov 05 '22 16:11

nanofarad


in Kotlin The structure of a test class would look like:

class MyTestClass {
    companion object {
        init {
           // things that may need to be setup before companion class member variables are instantiated
        }

        // variables you initialize for the class just once:
        val someClassVar = initializer() 

        // variables you initialize for the class later in the @BeforeClass method:
        lateinit var someClassLateVar: SomeResource 
  
        @BeforeClass @JvmStatic fun setup() {
           // things to execute once and keep around for the class
        }

        @AfterClass @JvmStatic fun teardown() {
           // clean up after this class, leave nothing dirty behind
        }
    }

    // variables you initialize per instance of the test class:
    val someInstanceVar = initializer() 

    // variables you initialize per test case later in your @Before methods:
    var lateinit someInstanceLateZVar: MyType 

    @Before fun prepareTest() { 
        // things to do before each test
    }

    @After fun cleanupTest() {
        // things to do after each test
    }

    @Test fun testSomething() {
        // an actual test case
    }

    @Test fun testSomethingElse() {
        // another test case
    }

    // ...more test cases
}  

Given the above, you should read about:

  • companion objects - similar to the Class object in Java, but a singleton per class that is not static
  • @JvmStatic - an annotation that turns a companion object method into a static method on the outer class for Java interop
  • lateinit - allows a var property to be initialized later when you have a well defined lifecycle
  • Delegates.notNull() - can be used instead of lateinit for a property that should be set at least once before being read.
like image 1
Mostafa Imani Avatar answered Nov 05 '22 17:11

Mostafa Imani