C3: Testing Exceptions

CPSC 210

Learning Goals

  • To design tests for methods that throw exceptions

That's it!

Tests need to deal with them too!

Throwing them in our tests doesn't make much sense

We should catch them!

This way we can also "expect" exceptions

Testing Exceptions

  • There are different ways to test exceptions with jUnit 4/5
    • ​We will focus on a simple (but sufficient) one
/*
 * Withdraw money from the account
 * MODIFIES: this
 * EFFECTS: amount is withdrawn from account and updated
 *            balance is returned; however, this instead:
 *          throws InsufficientFundsException if balance<amount
 *          throws NegativeAmountException if amount<0
 */
public double withdraw(double amount) 
    throws InsufficientFundsException, NegativeAmountException {
  • We need at least 3 test cases; one for the case without exceptions and two for the two exceptions
    • Normally we also check which exception is thrown if both conditions apply.. but that can't happen here

Test Case 1: Expect no exception

@Test
void testWithdrawNoException() {
  try {
    testAccount.withdraw(150.50);
  } catch (NegativeAmountException e) {
    fail("Unexpected NegativeAmountException");
  } catch (InsufficientFundsException e) {
    fail("Unexpected InsufficientFundsException");
  }
  assertEquals(349.50, testAccount.getBalance());
}
@Test
void testWithdrawNoException() {
  try {
    testAccount.withdraw(1000);
  } catch (InsufficientFundsException e) {
    fail("Caught unexpected InsufficientFundsException");
  } catch (NegativeAmountException e) {
    fail("Caught unexpected NegativeAmountException");
  }
  assertEquals(349.50, testAccount.getBalance());
}
@BeforeEach
void runBefore() {
  testAccount = new Account("Jane", 500.0);
}

Test Case 2&3: Expect exceptions

@Test
void testWithdrawInsufficientFundsException() {
  try {
    testAccount.withdraw(1000);
    fail("InsufficientFundsException was not thrown!");
  } catch (NegativeAmountException e) {
    fail("Unexpected NegativeAmountException");
  } catch (InsufficientFundsException e) {
    // all good!
  }
  assertEquals(500, testAccount.getBalance());
}
@BeforeEach
void runBefore() { testAccount = new Account("Jane", 500.0); }
@Test
void testWithdrawNegativeAmountException() {
  try {
    testAccount.withdraw(-10);
    fail("NegativeAmountException was not thrown!");
  } catch (NegativeAmountException e) {
    // all good!
  } catch (InsufficientFundsException e) {
    fail("Unexpected InsufficientFundsException");
  }
  assertEquals(500, testAccount.getBalance());
}

Test Case 4: Violating multiple

if (amount < 0) {
  throw new NegativeAmountException();
}
if (amount > getBalance()) {
  throw new InsufficientFundsException();
}
if (amount % 10 != 0) {
  throw new NotMultipleOfTenException();
}
  • What do we get if we call:
    • withdraw(50)
    • withdraw(600)
    • withdraw(-100)
    • withdraw(-111)
    • withdraw(-600)
    • withdraw(222)
    • withdraw(777) 
@BeforeEach
void runBefore() { testAccount = new Account("Jane", 500.0); }

Assume we had this code

Now we can generate test cases that
expect the right exception in each circumstance.

Lecture Ticket Review

// MODIFIES: this 
// EFFECTS: if numThings > 10 throws StressedOutException, otherwise
// does numThings things and returns the value of numThings
int doThings(int numThings) throws StressedOutException;
@Test
public void do3ThingsTestExpectReturn3() {
 int numThingsDone = 0;

 try {
   numThingsDone = doer.doThings(3);
   //POINT F

 } catch (StressedOutException soe) {
   //POINT A
 }
 //POINT B
}
@Test
public void do11ThingsTestExpectStressedOut() {
 int numThingsDone = 0;

 try {
   numThingsDone = doer.doThings(11);
   //POINT E

 } catch (StressedOutException soe) {
   //POINT C
 }
 //POINT D
}

No exception expected!

Exception
expected!

  • Q1: Which would you leave blank (or insert a comment)
  • Q2: Where would you insert a call to the fail method?
  • Q3/4: Where would you insert:
assertEquals(3, numThingsDone);
assertEquals(11, numThingsDone);

Lecture Lab

C3: Testing Exceptions

The End - Thank You!

CPSC210 - C3 Testing Exceptions

By Steven Wolfman

CPSC210 - C3 Testing Exceptions

  • 167