简体   繁体   中英

How to check multiple exceptions with one JUnit Method?

i have this code in my program which is needed to be tested with jUnit

 void deleteCustomer(String name) throws UnknownCustomerException,
        AccountNotEmptyException {
    if (name == null) {
        throw new NullPointerException();
    } else if (!exists(name)) {
        throw new UnknownCustomerException();
    } else if (getCustomer(name).deletable()) {
        customerList.remove(getCustomer(name));
    }
}

I thought i can test it in one JUnit method like

   @Test
public void createCustomer(){
    System.out.println("createCustomerTest");
    try {
        element.createCustomer(null);
        //fail("Expected an IndexOutOfBoundsException to be thrown");
    } catch (NullPointerException anIndexOutOfBoundsException) {
        assertTrue(anIndexOutOfBoundsException.getMessage().equals("NullPointerException"));
    }
}

As you can see I already tried unsuccessfully to implement the NPE. How can I check for several Exceptions in one JUnit Method? I checked some How-To's in the web but failed with that too.

I think in your case you should have separate tests, however you can achieve this like so if using Java 8:

Using an AssertJ 3 assertion, which can be used alongside JUnit:

import static org.assertj.core.api.Assertions.*;

@Test
public void test() {
  Element element = new Element();

  assertThatThrownBy(() -> element.createCustomer(null))
        .isInstanceOf(NullPointerException.class)
        .hasMessageContaining("NullPointerException");

  assertThatThrownBy(() -> element.get(1))
        .isInstanceOf(IndexOutOfBoundsException.class);
}

It's better than @Test(expected=IndexOutOfBoundsException.class) or .expect syntax because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message.

Maven/Gradle instructions here.

Write for each exception its own test. It will be only one thrown at a time anyway.
For example a simplified method:

    void deleteCustomer( String name ) throws UnknownCustomerException
    {
        if ( name == null )
        {
            throw new NullPointerException();
        }
        else if ( !exists( name ) )
        {
            throw new UnknownCustomerException();
        }
    }

You have then two tests that each check if its exception is thrown:

@Test( expected = NullPointerException.class )
public void deleteCustomer_shouldThrowNullpointerIfNameIsNull() throws UnknownCustomerException
{
    String name = null;
    cut.deleteCustomer( name );
}

@Test( expected = UnknownCustomerException.class )
public void deleteCustomer_shouldThrowUnknownCustomerExceptionIfNameIsUnknown() throws UnknownCustomerException
{
    String name = "someUnknownName";
    cut.deleteCustomer( name );
}

The problem with the NullpointerException is, that the test is true/successful/green if the NPE is thrown anywhere in the method - so you should make sure, that that is not happening for the test to be meaningful.

You could add several "catch" statement into the test method for different exceptions, like:

try {
    element.createCustomer(null);

    Assert.fail("Exception was expected!");
} catch (NullPointerException _ignore) {
} catch (UnknownCustomerException _ignore) {
}

or with Java 8 7

try {
    element.createCustomer(null);

    Assert.fail("Exception was expected!");
} catch (NullPointerException | UnknownCustomerException _ignore) {
}

But if you switch from JUnit to TestNG, then your test will be much cleaner:

@org.testng.annotations.Test(expectedExceptions = { NullPointerException.class, UnknownCustomerException.class })
public void createCustomer() throws NullPointerException, UnknownCustomerException {
    element.createCustomer(null);
}

More information about "expectedException" is here: http://testng.org/doc/documentation-main.html and example of the usage can be found here: http://www.mkyong.com/unittest/testng-tutorial-2-expected-exception-test/

I suggest that you take a closer look at the JavaDoc of ExpectedException and implement different tests for different validations, eg

 public class CustomerTest {

     @Rule
     public ExpectedException exception = ExpectedException.none();

     @Test
     public void throwsNullPointerExceptionForNullArg() {
        exception.expect(NullPointerException.class);

        element.createCustomer(null);
     }

     @Test
     public void throwsUnknwonCustomerExceptionForUnkownCustomer() {
        exception.expect(UnknownCustomerException.class);
        // exception.expectMessage("Some exception message"); uncomment to verify exception message

        element.createCustomer("unknownCustomerName");
     }

     @Test
     public void doesNotThrowExceptionForKnownCustomer() {

        element.createCustomer("a known customer");
        // this test pass since ExpectedException.none() defaults to no exception
     }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM