Advanced 30 min read

Build a Bulk-Safe Trigger

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

  • Write a before insert trigger applying validation, calculation, and status assignment together
  • Keep the trigger bulk-safe, following Module 25's discipline
  • Write a bulk test confirming 200 applications process correctly in one transaction

Prerequisites: "Enforce Validation Rules"

The trigger handler, combining everything so far

public class LoanApplicationTriggerHandler {
    private static final Integer LOAN_TERM_MONTHS = 60;

    public void beforeInsert(List<Loan_Application__c> newApplications) {
        LoanValidationService validator = new LoanValidationService();
        LoanCalculationService calculator = new LoanCalculationService();

        for (Loan_Application__c app : newApplications) {
            validator.validate(app.Requested_Amount__c, app.Annual_Income__c, app.Credit_Score__c);

            Decimal rate = calculator.calculateInterestRate(app.Credit_Score__c);
            app.Interest_Rate__c = rate;
            app.Monthly_Payment__c = calculator.calculateMonthlyPayment(app.Requested_Amount__c, rate, LOAN_TERM_MONTHS);
            app.Status__c = determineStatus(app.Credit_Score__c, app.Requested_Amount__c, app.Annual_Income__c);
        }
    }

    private String determineStatus(Decimal creditScore, Decimal amount, Decimal income) {
        if (creditScore >= 700 && amount <= income * 0.4) {
            return 'Pre-Approved';
        } else if (creditScore >= 600) {
            return 'Manual Review';
        } else {
            return 'Declined';
        }
    }
}

This is a genuinely realistic trigger handler — validation (Lesson 3), calculation (Lesson 2), and the approval decision (Lesson 1's policy, finally implemented) all working together, entirely in memory, no SOQL or DML inside the loop at all.

The bulk test, written immediately

@isTest
private class LoanApplicationTriggerHandlerTest {
    @isTest
    static void bulkApplicationsAllProcessCorrectly() {
        List<Loan_Application__c> applications = new List<Loan_Application__c>();
        for (Integer i = 0; i < 200; i++) {
            applications.add(new Loan_Application__c(
                Requested_Amount__c = 10000, Annual_Income__c = 50000, Credit_Score__c = 720
            ));
        }

        Test.startTest();
        insert applications;
        Test.stopTest();

        List<Loan_Application__c> saved = [SELECT Status__c, Interest_Rate__c FROM Loan_Application__c];
        System.assertEquals(200, saved.size());
        for (Loan_Application__c app : saved) {
            System.assertEquals('Pre-Approved', app.Status__c);
            System.assertEquals(6.5, app.Interest_Rate__c);
        }
    }
}

This is Module 31's "Testing Triggers: Bulk and Edge Cases" lesson, applied the moment the trigger exists — 200 records, one insert, and an assertion that every single one processed identically and correctly.

Exercise

Write a test inserting 3 applications with different credit scores (750, 650, 550) and asserting each gets the correct Status__c.

Show hint

Insert all 3 in one List, then query and check each one's Status__c individually.

APEX

Build a Bulk-Safe Trigger Quiz

1. How many DML statements does the trigger handler run for a batch of 200 applications?

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 wires the calculation and validation services into a real trigger, and — immediately — writes the bulk test that confirms it stays governor-limit-safe.