Async Apex needs special test patterns.
Pattern: wrap async operation in Test.startTest() / Test.stopTest(). Async runs synchronously when stopTest() called.
`apex @isTest static void testAsyncProcess() { Account a = new Account(Name='Test'); insert a;
Test.startTest(); AsyncProcessor.processAsync(a.Id); // queues async work Test.stopTest(); // <-- async runs here, synchronously
Account refreshed = [SELECT Status__c FROM Account WHERE Id=:a.Id]; System.assertEquals('Processed', refreshed.Status__c); } `
Specifics:
`@future`:
- Method must be static.
- Can't accept sObjects (only IDs).
- One future call per test method.
Queueable:
- Implement Queueable.
System.enqueueJob(myJob)queues.- One Queueable runs per
Test.stopTest(). - Chained Queueables: only first runs in test.
Batch:
- Execute via
Database.executeBatch(myBatch). - Test data goes through one batch chunk.
start(),execute(),finish()all run.
Schedulable:
System.schedule(jobName, cronString, new MyJob())queues.Test.stopTest()runs it.
Common pitfalls:
- Forgetting
Test.stopTest()— async never runs. - Querying before
Test.stopTest()— stale data. - Trying to test deep chain of Queueables — only first runs.
Senior insight: async testing is critical but tooling has limits. Test what you can; manual for chained scenarios.
