19

I would like to write a test for IndexOutOfBoundsException. Keep in mind that we are supposed to use JUnit 3.

My code:

public boolean ajouter(int indice, T element) {
    if (indice < 0 || indice > (maListe.size() - 1)) {
        throw new IndexOutOfBoundsException();
    } else if (element != null && !maListe.contains(element)) {
        maListe.set(indice, element);
        return true;
    }
}

After some research, I found that you can do this with JUnit 4 using @Test(expected = IndexOutOfBoundsException.class) but no where did I find how to do this in JUnit 3.

How can I test this using JUnit 3?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Mobidoy
  • 353
  • 1
  • 3
  • 11

6 Answers6

36

Testing exceptions in JUnit 3 uses this pattern:

try {
     ... code that should throw an exception ...

     fail( "Missing exception" );
} catch( IndexOutOfBoundsException e ) {
     assertEquals( "Expected message", e.getMessage() ); // Optionally make sure you get the correct message, too
}

The fail() makes sure you get an error if the code doesn't throw an exception.

I use this pattern in JUnit 4 as well since I usually want to make sure the correct values are visible in the exception message and @Test can't do that.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 1
    In JUnit 4, you can set an expected exception in @Test but you can also use [ExpectedExceptions](http://kentbeck.github.com/junit/javadoc/4.10/org/junit/rules/ExpectedException.html) which are more flexible and allow to check the message. – assylias Nov 06 '12 at 14:17
  • Ah, didn't know about this rule. It was added with JUnit 4.7. – Aaron Digulla Nov 06 '12 at 14:37
15

Basically, you need to call your method and fail if it doesn't throw the right exception - or if it throws anything else:

try {
  subject.ajouter(10, "foo");
  fail("Expected exception");
} catch (IndexOutOfBoundException expect) {
  // We should get here. You may assert things about the exception, if you want.
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

A simple solution is to add a try catch to the unittest and let the test fail when the exception isn't thrown

public void testAjouterFail() {
  try {
    ajouter(-1,null);
    JUnit.fail();
  catch (IndexOutOfBoundException()) {
    //success
  }
}
Janoz
  • 953
  • 4
  • 9
3

One thing you can do is use a boolean to run the test to completion and then you can use assert to validate the exception was thrown:

boolean passed = false;
try
{
    //the line that throws exception
    //i.e. illegal argument exception
    //if user tries to set the property to null:
    myObject.setProperty(null);
}
catch (IllegalArgumentException iaex)
{
    passed = true;
}
assertTrue("The blah blah blah exception was not thrown as expected"
              , passed);

By using this test, your test will never fail to execute and you can validate that a specific exception type is thrown.

COMCY2002
  • 81
  • 4
3

Extending @Aaron's solution with some (static import) syntactic sugar allows writing:

    expected(MyException.class,
        new Testable() {
            public void test() {
            ... do thing that's supposed to throw MyException ...
            }
        });

Testable is like a Runnable which uses test() signature throwing Throwable.

public class TestHelper {
    public static void expected(Class<? extends Throwable> expectedClass, Testable testable) {
        try {
            testable.test();
            fail("Expected "+ expectedClass.getCanonicalName() +" not thrown.");
        } catch (Throwable actual) {
            assertEquals("Expected "+ expectedClass.getCanonicalName() +" to be thrown.", expectedClass, actual.getClass());
        }
    }

    interface Testable {
        public void test() throws Throwable;
    }
}

You could add checking of the exception message as required.

karmakaze
  • 34,689
  • 1
  • 30
  • 32
2

In your test method, call ajouter() inside a try..catch block, giving a value of indice that should cause the exception to be thrown, with

  • a catch clause that catches IndexOutOfBoundsException: in that case return from your test method and thus indicate a pass.
  • a second catch clause that catches Throwable: in that case declare a failure (call fail()), because the wrong kind of exception was thrown
  • after the try..catch declare a failure (call fail()), because no exception was thrown.
Raedwald
  • 46,613
  • 43
  • 151
  • 237