afv-library/skills/generating-apex-test/SKILL.md
Jeff Douglas bba4327cd8
Add Apex & Unit Test Skills (#105)
* added apex and apex test
2026-03-25 14:07:54 -04:00

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

  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

@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_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:

Reference Files

Detailed patterns for specific scenarios:

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