Advanced 30 min read

Test Edge Cases and Exceptions

By the end of this lesson, you'll be able to:

  • Test the exact validation boundaries (credit score 300 and 850)
  • Test a batch containing both valid and invalid applications together
  • Explain what happens to the whole batch when one record fails validation

Prerequisites: "Write Comprehensive Tests"

Testing the exact validation boundaries

@isTest
static void creditScoreOf300IsValid() {
    LoanValidationService validator = new LoanValidationService();
    validator.validate(10000, 50000, 300); // should not throw
    System.assert(true);
}

@isTest
static void creditScoreOf299IsInvalid() {
    LoanValidationService validator = new LoanValidationService();
    try {
        validator.validate(10000, 50000, 299);
        System.assert(false, 'Expected a LoanValidationException');
    } catch (LoanValidationException e) {
        System.assert(e.getMessage().contains('Credit score'));
    }
}
  1. @isTest — marks the first test.
  2. static void creditScoreOf300IsValid() { — 300 — the exact edge of the valid range.
  3. LoanValidationService validator = new LoanValidationService(); — creates the validator.
  4. validator.validate(10000, 50000, 300); — should not throw.
  5. System.assert(true); — confirms it didn't.
  6. } — closes this test.
  7. (blank line)
  8. @isTest — marks the second test.
  9. static void creditScoreOf299IsInvalid() { — the value one below the boundary.
  10. LoanValidationService validator = new LoanValidationService(); — creates the validator.
  11. try { — wraps the call expected to throw.
  12. validator.validate(10000, 50000, 299); — 299 — precisely where a < vs <= mistake in LoanValidationService.validate() would hide.
  13. System.assert(false, 'Expected a LoanValidationException'); — reached only if it didn't throw.
  14. } catch (LoanValidationException e) { — catches the expected failure.
  15. System.assert(e.getMessage().contains('Credit score')); — verifies the right error, exactly like the 599/600 boundary from the previous lesson.
  16. } — closes the try/catch.
  17. } — closes this test.

A batch with one invalid application

@isTest
static void oneInvalidApplicationInABatchBlocksTheWholeInsert() {
    List<Loan_Application__c> applications = new List<Loan_Application__c>{
        LoanTestDataFactory.createQualifyingApplication(),
        LoanTestDataFactory.createApplication(-5000, 50000, 720) // invalid: negative amount
    };

    try {
        insert applications;
        System.assert(false, 'Expected a DmlException from the invalid second record');
    } catch (DmlException e) {
        System.assert(e.getMessage().contains('amount'));
    }

    System.assertEquals(0, [SELECT COUNT() FROM Loan_Application__c]);
}
  1. @isTest — marks the test method.
  2. static void oneInvalidApplicationInABatchBlocksTheWholeInsert() { — the test.
  3. List<Loan_Application__c> applications = new List<Loan_Application__c>{ — a batch with one good and one bad record.
  4. LoanTestDataFactory.createQualifyingApplication(), — a perfectly valid application.
  5. LoanTestDataFactory.createApplication(-5000, 50000, 720) — an invalid one, with a negative amount.
  6. }; — closes the list literal.
  7. (blank line)
  8. try { — wraps the insert expected to fail.
  9. insert applications; — because beforeInsert throws an exception (via validate()) for the second application, the entire insert statement fails — not just the bad record.
  10. System.assert(false, 'Expected a DmlException from the invalid second record'); — reached only if it unexpectedly succeeded.
  11. } catch (DmlException e) { — catches the expected failure.
  12. System.assert(e.getMessage().contains('amount')); — verifies the right error.
  13. } — closes the try/catch.
  14. (blank line)
  15. System.assertEquals(0, [SELECT COUNT() FROM Loan_Application__c]); — confirms this explicitly: zero applications were saved, including the perfectly valid first one, exactly the all-or-nothing DML behavior from Module 19.
  16. } — closes the test method.

Exercise

Write a test confirming that inserting a batch of 3 valid applications and 1 with an out-of-range credit score (900) throws and saves nothing.

Show hint

Follow the try/System.assert(false)/catch pattern, then assert zero records were saved.

APEX

Test Edge Cases and Exceptions Quiz

1. What happens to the valid applications in a batch when one application in that same batch fails validation?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

This lesson tests the genuinely tricky edge cases: the exact validation boundaries, and — critically — what happens when a bulk insert mixes valid and invalid applications in the same batch.