Async testing requires careful use of Test.startTest() and Test.stopTest() to force async work to run synchronously inside the test.
Pattern:
`apex @isTest static void testAsync() { Account acc = new Account(Name='Test'); insert acc;
Test.startTest(); MyClass.doFutureWork(acc.Id); // async work queued Test.stopTest(); // <-- async work runs HERE, synchronously
Account refreshed = [SELECT Phone FROM Account WHERE Id=:acc.Id]; System.assertEquals('updated', refreshed.Phone); } `
Key rules:
- `Test.startTest()` resets governor limits for the test code that follows. Useful for isolating limit usage.
- `Test.stopTest()` flushes async work —
@future, Queueable, Batch jobs queued during the test all execute synchronously whenstopTestis called. - Without
stopTest, async work doesn't run during the test; you can't assert on its effects.
Specifics by async type:
`@future`:
- Test calls the future method between startTest/stopTest. The work runs at stopTest.
- Cannot test future call from within another future (Salesforce restriction).
Queueable:
- Same pattern. The Queueable's
execute()runs synchronously at stopTest. - For chained Queueables: only the FIRST chain link runs in the test. Subsequent links require additional test-method invocations or the chain is mocked.
Batch Apex:
- Same pattern, but the test must process records you've inserted.
start()returns the QueryLocator (or iterable); test setup must populate the source records.execute()runs once per chunk. In tests, the entire query result becomes one chunk regardless of batch size — keep test data small.finish()runs at the end.
Common pitfalls:
- Forgetting
Test.stopTest()— async never runs, assertions fail. - Trying to chain Queueables in test — can't easily test deep chains.
- Querying for the result before
stopTest— async hasn't run yet, results are stale. - Not setting up enough test data to make assertions meaningful.
Mocking external callouts in async tests:
- Use
Test.setMock(HttpCalloutMock.class, new MyMock())— works in async too.
The async test pattern is one of the most common interview questions and most common production-code mistakes.
