Apex 测试
Apex 提供完整的测试框架——编写单元测试、运行测试、查看结果和代码覆盖率。部署前要求:单元测试必须覆盖至少 75% 代码且全部成功、每个触发器必须有测试覆盖、所有类和触发器必须编译成功。隐私保护:测试错误消息和异常详情不应包含个人数据——创建 Exception 子类将敏感数据放在属性中而非消息字符串中。
理解 Apex 测试
为何测试:关键是应用成功——尤其部署给客户时。UI 手动测试不涵盖所有用例——批量功能测试(SOAP API/标准集控制器可传递最多 200 条记录)同样重要。全面测试确保新增功能不引入回归。强烈推荐测试驱动开发(TDD)——测试开发与代码开发同时进行。
测试什么
测试所有代码——尤其关注:单条记录操作(触发器单记录插入/更新/删除)、批量操作(200 条记录——批量触发器最重要的测试场景)、正向用例(预期成功场景——验证正确行为)、负向用例(错误处理——验证验证规则/必填字段/权限检查的异常行为)、边界条件(最大/最小值、null 值、空集合)。测试用户权限——使用 System.runAs() 切换不同用户配置文件验证权限行为。
Apex 单元测试
@isTest 注解:标记类和方法为测试代码——不计入组织 6MB Apex 代码限制。测试方法必须是 static void——不接受参数、不向数据库提交数据、不发送邮件。@isTest(SeeAllData=true) 授予测试方法访问组织中所有数据的权限——慎用(可能因数据变化导致测试不稳定)。@isTest(isParallel=true) 允许测试类并行执行。
测试数据:Apex 测试数据是瞬时的——不提交到数据库。测试在独立隔离的执行上下文中运行——对其他测试不可见。@testSetup 方法——创建所有测试方法共享的测试数据(每个类只执行一次 setup——比每个方法单独创建数据更高效)。Test.loadData(StaticResource, csv) 从 StaticResource 的 CSV 文件加载测试记录。
@TestVisible 与访问私有成员
@TestVisible:使 private/protected 成员在测试代码中可见——允许测试私有方法或变量而无需降低封装级别。用于需要测试内部逻辑但不想暴露为 public 的场景。仅应用于测试需求的成员。
使用 runAs、Limits、startTest/stopTest
System.runAs(user):以指定用户身份执行代码——在 runAs 块内混合 DML(setup + non-setup sObject)不受限制。用户必须已插入数据库。在 runAs 块内创建的记录归该用户所有。不影响用户权限本身——需要用户的 profile/permission set 设置适当的权限。
Test.startTest()/stopTest():startTest 标记测试开始——重置 Governor Limit 为测试独有的更高限制。stopTest 同步执行所有已排队的异步操作(Future/Queueable/Batch——最多 1 个 Batch)。startTest/stopTest 之间可验证 Governor Limit 使用情况——Limits.getQueries() 等。
SOSL 查询在测试中:默认不返回结果——需要通过 Test.setFixedSearchResults(ids) 注册预期结果。需要为每个测试方法单独注册。
测试最佳实践与并行执行
最佳实践:每个测试方法只验证一个用例——使失败原因清晰。使用 @testSetup 减少重复数据创建。在 startTest 之前创建数据——startTest 之后 Governor Limit 重置。使用 System.assert/assertEquals/assertNotEquals 验证预期结果——至少一个断言。批量测试(200 条记录)是最重要的测试场景——验证触发器批量正确性。测试异常处理——使用 try-catch 或在 DML 中使用 Database 方法捕获部分失败。
并行测试执行:@isTest(isParallel=true) 允许并行——减少总测试执行时间。但并行测试间必须无数据依赖——不能共享静态变量或修改共享数据。测试中不使用 SeeAllData=true 时并行更安全。
代码覆盖率
每次运行测试时生成覆盖率数据——表示类和触发器中多少可执行代码行被测试方法执行。部署要求:整体代码覆盖率至少 75%——System.debug 不计入覆盖率、测试方法和测试类不计入覆盖率。最佳实践:不要只关注 75% 数字——确保覆盖所有用例(正向+负向+批量+单条)。复杂逻辑方法需要多个测试覆盖不同分支路径。使用 Developer Console → Tests → Overall Code Coverage 查看逐类覆盖率。定期检查未覆盖代码行——可能是死代码或缺少测试的信号。
Stub API 构建 Mock 框架
System.StubProvider 接口:实现 handleMethodCall 方法——在 mock 对象上调用方法时执行。通过 Test.createStub(classType, stubProvider) 创建 mock 对象——运行时动态生成(不需要打包部署测试类)。Stub 对象的类型在运行时动态创建——节省打包空间。用于隔离测试(不依赖真实依赖项)、模拟外部服务响应、注入错误场景。可构建自己的 mocking 框架或使用现成的(如 ApexMocks)。
Apex 集成测试(Developer Preview)
@IntegrationTest 注解:编写端到端测试——测试 Salesforce org 与 Agentforce/Data 360 等服务之间的真实交互。与标准单元测试的关键差异:放宽 callout 限制(可进行真实服务调用)、允许事务中提交数据(与标准测试全部回滚不同)、可在提交后做断言验证预期结果。仅在Scratch Org 中可用——不可在生产 org 或元数据部署中运行。类只能包含集成测试方法和 @TearDown 方法——不能与 @IsTest 混合。@TearDown 方法在测试完成后运行(无论通过或失败)用于清理。
系统化的测试策略——从单元测试到代码覆盖率到 Stub API Mock 到集成测试——是构建高质量、可维护 Apex 应用的基石。