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). @testSetupcreates 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 atstopTest().- Test bulk (200+ records), positive, negative and permission scenarios.
- Prefer
Assert.areEqual/Assert.isTrue(orSystem.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
- Minimum coverage to deploy? → 75% overall, all tests passing, every trigger covered.
- What do
Test.startTest()andTest.stopTest()do? - Why avoid
SeeAllData=true? → Tests become dependent on org data and break between orgs. - How do you test a callout? →
HttpCalloutMockwithTest.setMock.