Search code examples
javajunitjunit4junit-rule

JUnit does not seem to be invoking my overridden TestWatcher failed/succeeded methods


Note: The code for MyTest has been updated to reflect the answer I found, which is caused by multiple implementations of assertEquals() being available in JUnit's ecosystem.

I've seen a similar question in C, but no answer/responses. I've either taken a left turn on the implementation, or am overlooking something simple. So...

I'd expect to see the "IT FAILED" and "IT PASSED" on the console, but no joy. Just the "testFailure()" and "testSuccess()" output.

TestRunner impl

import junit.runner.Version; // added to support version check
import org.junit.runner.JUnitCore;

public class TestRunner {
    public static void main(String[] args) {
        System.out.println(Version.id()); // added to check JUnit version
        JUnitCore.runClasses(MyTest.class);
    }
}

Test impl

// NO LONGER NEDED (v3 -v- v4) import junit.framework.TestCase;
import org.junit.Rule;
import org.junit.Test;
import ort.junit.Assert.assertEquals; // version that invokes TestWatcher

// public class MyTest extends TestCase {  // JUnit v3.X semantics 
public class MyTest {                      // JUnit v4.X semantics

    @Rule
    public MyTestWatcher myTestWatcher = new MyTestWatcher();

    @Test
    public void testFailure() {
        System.out.println("testFailure()");
        assertEquals("failure", true, false);
    }

    @Test
    public void testSuccess() {
        System.out.println("testSuccess()");
        assertEquals("failure", true, true);
    }
}

TestWatcher impl

import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class MyTestWatcher extends TestWatcher {

    public MyTestWatcher() {}

    @Override
    protected void failed(Throwable e, Description description) {
        System.out.println("IT FAILED");
    }

    @Override
    protected void succeeded(Description description) {
        System.out.println("IT PASSED");
    }
}

Solution

  • The root cause is the backwards compatibility between JUnit v3.X and JUnit v4.X. It's nice, but it injected an interesting overload on the assertion statements.

    In my original code, the method being invoked was org.junit.framework.TestCase.assertEquals(). However, this version of assertEquals() does not seem to invoke TestWatcher.failed() and TestWatcher.succeeded(). So, while the code "ran successfully", it did not output the desired logging information (i.e., "IT FAILED"/"IT PASSED").

    The solution was to make sure that the assert statements are invoking the correct implementation (i.e., those in org.junit.Assert). The simplest way to do this was to modify the test to conform to v4.X semantics (i.e., not extend TestCase), and then add the correct import statement.

    With these modifications to MyTest, everything now works as expected. I have updated my original post to show where modifications were made.