Cause of an unexpected behaviour using JUnit 4'

2019-04-21 09:52发布

I am trying to test that a particular method throws an expected exception from a method. As per JUnit4 documentation and this answer I wrote the test as:

@Test(expected=CannotUndoException.class)  
public void testUndoThrowsCannotUndoException() {   
    // code to initialise 'command'

    command.undo();
}

However, this code fails the JUnit test, reporting the thrown (and expected) exception as an error.

The method I'm testing has only this in the body:

public void undo() {
    throw new CannotUndoException();
}

Furthermore, the following test passes:

public void testUndoThrowsCannotUndoException() {
    // code to initialise 'command'

    try { 
        command.undo();
        fail();
    } catch (CannotUndoException cue){

    }
}

Meaning that the expected exception is actually thrown.

I am actually planning to change the method to actually do something, rather than just throw the exception, but it's got me curious as to what caused the problem, lest it should happen again in the future.

The following checks have been made:

  • the CannotUndoException imported into the test case is the correct one
  • version 4 of JUnit is the only one on my classpath
  • a clean and build of Eclipse workspace did not change the outcome

I am using JUnit 4.1, and in the same test I am using Mockito.

What could be causing the erroneous failure?

4条回答
再贱就再见
2楼-- · 2019-04-21 10:08

I have found the problem.

The TestRunner I was using was the correct one (JUnit 4), however, I declared my test class as:

public class CommandTest extends TestCase

Which I assume is causing the test runner to treat it as a JUnit 3 test. I removed extends TestCase and received the expected results.

查看更多
Viruses.
3楼-- · 2019-04-21 10:08

Curious.

I wrote three classes:

An UndoCommand:

public class UndoCommand
{
    public void undo()
    {
        throw new CannotUndoException();
    }
}

A CannotUndoException:

// Note: extends the unchecked superclass RuntimeException
public class CannotUndoException extends RuntimeException
{
    public CannotUndoException()
    {
        super();
    }

    public CannotUndoException(String message)
    {
        super(message);
    }

    public CannotUndoException(String message, Throwable cause)
    {
        super(message, cause);
    }

    public CannotUndoException(Throwable cause)
    {
        super(cause);    
    }
}

And a JUnit 4.4 test class:

import org.junit.Test;

public class UndoCommandTest
{
    @Test(expected=CannotUndoException.class)
    public void testUndo()
    {
        UndoCommand command = new UndoCommand();

        command.undo();
    }
}

Works perfectly - all tests pass, "green" result.

If I remove the (expected=...) from the annotation the test fails, as expected.

I'm using Sun JDK 6, JUnit 4.4 and IntelliJ 7.0.5.

How does yours differ?

查看更多
萌系小妹纸
4楼-- · 2019-04-21 10:22

I had a similar problem and I fixed it by adding the annotation

@RunWith(JUnit4ClassRunner.class)

Which tells the unit tester to run it with the 4er version of Junit

查看更多
Fickle 薄情
5楼-- · 2019-04-21 10:29

Your test code looks ok to me.

Check that you're running with a junit 4 testrunner, not a junit 3.8 testrunner - this could very well be the culprit here (try launching from the command line or just visually inspect the command line when running your test). The classpath of your testrunner may not be the same as your project classpath

This is particularly the case inside IDE's. Alternately you could also try to push to junit 4.4 and see if that solves your problem. (junit 4.5 may cause other problems).

查看更多
登录 后发表回答