@Before method in TestRule is not called
Asked Answered
N

2

12

I implemented a JUnit 4 TestRule (extending an ExternalResource), and injected it as a @ClassRule in my test class: I want to initialize a resource once for all in every test of this class, and tear it down eventually.

My issue is that my @Before and @After rule-methods are not called at all before/after my @Test method: any idea why this is happening?

Minimal compilable example:

package com.acme.test;

import static org.junit.Assert.assertNull;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

class Coffee {
    public void throwAway() {}
}

class CoffeeMachine extends ExternalResource {
    Coffee whatElse;    
    @Override protected void before() throws Throwable {
        whatElse = new Coffee();
    }

    @Override protected void after() {
        whatElse.throwAway();
    }

    public Coffee gimmieCoffee() { return whatElse; }
}

public class CoffeeTester {
    @ClassRule public static CoffeeMachine CM = new CoffeeMachine();

    @Test public void drinkACoffee() {
        Coffee c = CM.gimmieCoffee();
        assertNull(c);  // ---> Coffee is null!!                       (fuuuuuuuuuu...)
    }
}

Is there something I am misunderstanding here? Note that the same happens with a non-static @Rule.

I am using JUnit 4.11.

Thank you very much for any hint.

Nanosecond answered 12/5, 2015 at 15:29 Comment(14)
shouldn't the @Before be in the same class as the @Test? I'm also not sure if overriding before() will suffice if it is not also taggedHobble
Not like that... but thank you Dragondraikk.Nanosecond
You clearly haven't tried the code you've provided, because you've got too many ms in the call to gimmieCoffee - and no imports. I've fixed up those things, and it's fine. Please provide an example which compiles and actually demonstrates the issue.Nitroglycerin
Jon, I just wanted to represent a minimal example, I did not run my coffee machine, but a typo does not really matter here, I was more trying to discover some more fundamental mistake I was doing here.Nanosecond
If I wanted to let you run the code, I would have posted a Coffee class too. Thanks for trying to help anyway Jon. I personally don't see this as a -1 question.Nanosecond
The example is now complete for copy-paste-compile ;)Nanosecond
@Nanosecond if you want people to help with your question, the minimal code you post really should compile and be copy-pastable. I have run your code, as it stands above, and the before() and after() are being called. The assertNull(c) line for me gives: java.lang.AssertionError: expected null, but was:<com.steve.research.Coffee@17050f5>. I can't see why it isn't working for you. Running junit 4.11 and java 7 here.Competence
@vikingsteve: ..but my example is indeed directly compilable.. (thanks Jon) Anyway, good to know that it works for you there. The only difference here is that I am using Java 8 and that I tried within Eclipse IDE (Luna). I'll try to run this example manually, and as well with Java 7.Nanosecond
Coffee is null here, with Java 7 too.Nanosecond
It seems it is a problem with the version of JUnit shipped with Eclipe. I tried running the test via commad-line using v4.12, and all works as expected. It seems it is not really easy to change the version of JUnit used by Eclipse run configurations. #10779656Nanosecond
If different classloaders are used, such strange phenomena can also happen. Can you add System.out.println(this.getClass().getClassLoader()); in before() and in drinkACoffee() and run the test again?Twaddle
Hey @mmirwaldt: thanks for chiming in. Here is it: sun.misc.Launcher$AppClassLoader@30dae81Nanosecond
Is that the class loader for both outputs? If it is the same, my assumption is false.Twaddle
There are no @Before and @After annotations in the code...Gardell
F
5

I think this is a problem with your test runner. Maybe some plugin has installed a custom runner which is used when you run your tests from Ecilpse?

Check the run configuration for your test and make sure that the standard JUnit 4 test runner is used:

enter image description here

Fatuous answered 19/5, 2015 at 6:35 Comment(1)
Hey thanks for this, but I checked it already: all is plain regular.Nanosecond
H
3

I see no issue here, but just a misunderstanding. First of all, let's read assert as it must be and change your code a bit (it is obvious your test says c must not be null which gives us: assertNotNull(c);

I've also added some output in order to show you what is going on. Please try to run it.

package com.acme.test;

import static org.junit.Assert.assertNotNull;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

class Coffee {
    public void throwAway() {}
}

class CoffeeMachine extends ExternalResource {
    Coffee whatElse;    
    @Override protected void before() throws Throwable {
        whatElse = new Coffee();
        System.out.println(" ### executing before: " + whatElse);
    }

    @Override protected void after() {
        whatElse.throwAway();
    }

    public Coffee gimmieCoffee() { return whatElse; }
}

public class CoffeeTester {
    @ClassRule public static CoffeeMachine CM = new CoffeeMachine();

    @Test public void drinkACoffee() {
        Coffee c = CM.gimmieCoffee();
        System.out.println(" ### executing test: " + c);
        assertNotNull(c); 
    }
}

For me it gives the following:

 ### executing before: com.acme.test.Coffee@28f67ac7
[VerboseTestNG] INVOKING: "com.acme.test.CoffeeTester" - com.acme.test.CoffeeTester.drinkACoffee()
 ### executing test: com.acme.test.Coffee@28f67ac7
[VerboseTestNG] PASSED: "com.acme.test.CoffeeTester" - com.acme.test.CoffeeTester.drinkACoffee() finished in 4 ms
[VerboseTestNG] 
[VerboseTestNG] ===============================================
[VerboseTestNG]     com.acme.test.CoffeeTester
[VerboseTestNG]     Tests run: 1, Failures: 0, Skips: 0
[VerboseTestNG] ===============================================

So c is not null as you expect it to be.

Homothallic answered 15/5, 2015 at 10:52 Comment(6)
thank you for the help! I get ### executing test: null however. :)Nanosecond
That is really fascinating :) Did you try another JUnit version? Can you provide check-sum of the jar you have?Homothallic
I use the JUnit which is shipped with Eclipse: org.junit_4.11.0.v201303080030/. Checksum is fine .. I tried now with 4.12, my initial example works fine.Nanosecond
@Campa, basically I just want us to have a proof your Eclipse environment is a bit "spoiled". BTW, do not forget to verify jars checksums in my archive or simply replace them.Homothallic
I ran ant in the project folder, and the test runs successfully both with your JARs and with the ones shipped with Eclipse. Guess I should report this in the Eclipse forums. ?Nanosecond
I believe Eclipse is widely used, so it should not have such obvious issues. I can only suggest to experiment a bit (create a new project, play with executors a bit) in order to narrow down list of possible explanations.Homothallic

© 2022 - 2024 — McMap. All rights reserved.