--- name: generating-apex-test description: "Apex test class generation with TestDataFactory patterns, bulk testing (200+ records), mocking strategies for callouts and async operations, and assertion best practices. Use this skill when the user asks to create, write, or generate an Apex test class, improve test coverage, refactor existing tests, or implement proper testing patterns for triggers, services, controllers, batch jobs, queueables, and integrations — even when they don't say 'test' explicitly. Activate on phrases like: 'write tests for,' 'add coverage for,' 'test this class,' 'create a mock,' 'I need test data,' 'improve coverage,' or any mention of Apex testing, assertions, or test factories." --- # Apex Test Class Skill ## Core Principles 1. **Bulkify tests** - Always test with 200+ records to catch governor limit issues 2. **Isolate test data** - Use `@TestSetup` and TestDataFactory; never rely on org data 3. **Assert meaningfully** - Test behavior, not just coverage; include failure messages 4. **Mock external dependencies** - Use `HttpCalloutMock`, `Test.setMock()` for integrations 5. **Test negative paths** - Validate error handling, not just happy paths ## Test Class Structure ```apex @isTest private class MyServiceTest { @TestSetup static void setupTestData() { // Create shared test data using TestDataFactory List accounts = TestDataFactory.createAccounts(200, true); } @isTest static void shouldPerformExpectedBehavior_WhenValidInput() { // Given: Setup specific test state List accounts = [SELECT Id, Name FROM Account]; // When: Execute the code under test Test.startTest(); MyService.processAccounts(accounts); Test.stopTest(); // Then: Assert expected outcomes List 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 emptyList = new List(); // 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_WhenAccountIsActive` - `shouldThrowException_WhenEmailIsInvalid` - `shouldSendNotification_WhenOpportunityClosedWon` - `shouldBypassTrigger_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](assets/test-class-template.cls)** - Starter test class with positive, negative, bulk, and governor limit test stubs - **[assets/test-data-factory-template.cls](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](references/test-data-factory.md)** - TestDataFactory class patterns and field defaults - **[references/assertion-patterns.md](references/assertion-patterns.md)** - Assertion best practices and common pitfalls - **[references/mocking-patterns.md](references/mocking-patterns.md)** - HttpCalloutMock, Test.setMock(), stubbing - **[references/async-testing.md](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 |