Apex Testing

Test classes, data factories, startTest/stopTest, assertions, bulk tests and mocking callouts.

Developer 2 min readTestingCode coverageTest data

Production deployments need at least 75% overall code coverage, every trigger needs some coverage, and all tests must pass. Good tests also assert behavior — coverage alone proves nothing.

A complete test class

apex
@isTest
private class AccountRatingTriggerTest {

    @testSetup
    static void setup() {
        insert new Account(Name = 'Existing', AnnualRevenue = 10);
    }

    @isTest
    static void setsRatingFromRevenue_bulk() {
        List<Account> accs = new List<Account>();
        for (Integer i = 0; i < 200; i++) {
            accs.add(new Account(Name = 'Acc ' + i, AnnualRevenue = i * 10000));
        }

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

        Integer hot = [SELECT COUNT() FROM Account WHERE Rating = 'Hot'];
        Assert.areEqual(0, hot, 'No account reaches 1M in this data set');
        Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Rating = null AND Name LIKE 'Acc %']);
    }
}

Key ideas

  • Test data is isolated and rolled back — tests don't see org data (unless @isTest(SeeAllData=true), which you should avoid).
  • @testSetup creates data once per class; each test method gets its own copy.
  • Test.startTest() / Test.stopTest() give the code under test a fresh set of governor limits and force async jobs to finish at stopTest().
  • Test bulk (200+ records), positive, negative and permission scenarios.
  • Prefer Assert.areEqual / Assert.isTrue (or System.assertEquals) with messages.

Test data factory

apex
@isTest
public class TestDataFactory {
    public static List<Account> accounts(Integer n, Boolean doInsert) {
        List<Account> accs = new List<Account>();
        for (Integer i = 0; i < n; i++) accs.add(new Account(Name = 'Test ' + i));
        if (doInsert) insert accs;
        return accs;
    }
}

Testing as another user

apex
User u = [SELECT Id FROM User WHERE Profile.Name = 'Standard User' AND IsActive = true LIMIT 1];
System.runAs(u) {
    // assert sharing / permission behavior
}

Mocking HTTP callouts

apex
@isTest
public class WeatherMock implements HttpCalloutMock {
    public HttpResponse respond(HttpRequest req) {
        HttpResponse res = new HttpResponse();
        res.setStatusCode(200);
        res.setBody('{"temp": 21}');
        return res;
    }
}

Test.setMock(HttpCalloutMock.class, new WeatherMock());

Real callouts are not allowed in tests.

Interview questions

  1. Minimum coverage to deploy? → 75% overall, all tests passing, every trigger covered.
  2. What do Test.startTest() and Test.stopTest() do?
  3. Why avoid SeeAllData=true? → Tests become dependent on org data and break between orgs.
  4. How do you test a callout? → HttpCalloutMock with Test.setMock.

Practice this