mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-04 14:25:31 +08:00
4.2 KiB
4.2 KiB
| name | description |
|---|---|
| generating-apex-test | Apex test class generation with TestDataFactory patterns, bulk testing (200+ records), mocking strategies, and assertion best practices. Use this skill when the user asks to create, write, or improve Apex test classes, add coverage, build mocks, or implement testing patterns for triggers, services, batch jobs, queueables, and integrations. |
Apex Test Class Skill
Core Principles
- Bulkify tests - Always test with 200+ records to catch governor limit issues
- Isolate test data - Use
@TestSetupand TestDataFactory; never rely on org data - Assert meaningfully - Test behavior, not just coverage; include failure messages
- Mock external dependencies - Use
HttpCalloutMock,Test.setMock()for integrations - Test negative paths - Validate error handling, not just happy paths
Test Class Structure
@isTest
private class MyServiceTest {
@TestSetup
static void setupTestData() {
// Create shared test data using TestDataFactory
List<Account> accounts = TestDataFactory.createAccounts(200, true);
}
@isTest
static void shouldPerformExpectedBehavior_WhenValidInput() {
// Given: Setup specific test state
List<Account> accounts = [SELECT Id, Name FROM Account];
// When: Execute the code under test
Test.startTest();
MyService.processAccounts(accounts);
Test.stopTest();
// Then: Assert expected outcomes
List<Account> updated = [SELECT Id, Status__c FROM Account];
System.assertEquals(200, updated.size(), 'All accounts should be processed');
for (Account acc : updated) {
System.assertEquals('Processed', acc.Status__c, 'Status should be updated');
}
}
@isTest
static void shouldThrowException_WhenInvalidInput() {
// Given
List<Account> emptyList = new List<Account>();
// When/Then
Test.startTest();
try {
MyService.processAccounts(emptyList);
System.assert(false, 'Expected MyCustomException to be thrown');
} catch (MyCustomException e) {
System.assert(e.getMessage().contains('cannot be empty'),
'Exception message should indicate empty input');
}
Test.stopTest();
}
}
Naming Convention
Use descriptive method names: should[ExpectedBehavior]_When[Condition]
Examples:
shouldCreateContact_WhenAccountIsActiveshouldThrowException_WhenEmailIsInvalidshouldSendNotification_WhenOpportunityClosedWonshouldBypassTrigger_WhenRunningAsBatch
Test.startTest() / Test.stopTest()
Always wrap the code under test:
- Resets governor limits for accurate limit testing
- Executes async operations synchronously (queueables, batch, future)
- Fires scheduled jobs immediately
Asset Templates
Ready-to-use scaffolds for common test patterns:
- assets/test-class-template.cls - Starter test class with positive, negative, bulk, and governor limit test stubs
- assets/test-data-factory-template.cls - TestDataFactory with Account, Contact, Opportunity, User factories and field override support
Reference Files
Detailed patterns for specific scenarios:
- references/test-data-factory.md - TestDataFactory class patterns and field defaults
- references/assertion-patterns.md - Assertion best practices and common pitfalls
- references/mocking-patterns.md - HttpCalloutMock, Test.setMock(), stubbing
- references/async-testing.md - Batch, Queueable, Future, Scheduled job testing
Quick Reference: What to Test
| Component | Key Test Scenarios |
|---|---|
| Trigger | Bulk insert/update/delete, recursion, field changes |
| Service | Valid/invalid inputs, bulk operations, exceptions |
| Controller | Page load, action methods, view state |
| Batch | Start/execute/finish, chunking, error records |
| Queueable | Chaining, bulkification, error handling |
| Callout | Success response, error response, timeout |
| Scheduled | Execution, CRON validation |