测试 Shipping Invoice 应用:完整示例与最佳实践总结

Shipping Invoice测试应用完整示例:Calculate触发器(Map收集唯一InvoiceID/批量SOQL/subtract标志三种操作模式/updateMap.values批量DML)、ShippingDiscount触发器(before insert条件折扣)、测试类(@testSetup共享数据/每种操作正向+负向/insert+update+delete+discount五种验证/Test.startTest+stopTest)、应用架构总结(触发器逻辑分离Handler/Map+Set批量数据处理/事务原子性/Governor Limit意识)。...

📅 2026/7/16 ✍️ ponybai 🏷️ apex, salesforce

测试 Shipping Invoice 应用

Shipping Invoice

在将应用程序打包到 AppExchange 之前,75% 的代码必须被单元测试覆盖。本章展示 Shipping Invoice 示例应用的完整测试实现——包括触发器代码、测试类和最佳实践总结。

Calculate 触发器:批量处理模式

Calculate触发器

Calculate 触发器在 Line Item 插入/更新/删除后自动重新计算 Invoice 的总额。关键技术:使用 Map 收集唯一 Invoice ID(Map 不允许重复键——自动去重)、根据触发器类型设置 subtract 标志(插入/更新=1,删除=-1)、批量 SOQL 查询相关 Invoice 和 Line Item、循环更新每条 Invoice 的总额。遵循批量触发器最佳实践——不使用 Trigger.new[0] 假设单条记录

trigger calculate on Item__c (after insert, after update, after delete) {
    Map<ID, Invoice__c> updateMap = new Map<ID, Invoice__c>();
    Integer subtract;
    List<Item__c> itemList;
    if (trigger.isInsert || trigger.isUpdate) {
        itemList = Trigger.new;
        subtract = 1;
    } else if (trigger.isDelete) {
        itemList = Trigger.old;
        subtract = -1;
    }
    for (Item__c item : itemList) {
        if (!updateMap.containsKey(item.Invoice__c)) {
            updateMap.put(item.Invoice__c, new Invoice__c(Id = item.Invoice__c, Total__c = 0));
        }
    }
    for (Item__c item : [SELECT Id, Cost__c, Invoice__c FROM Item__c
        WHERE Invoice__c IN :updateMap.keySet()]) {
        Invoice__c inv = updateMap.get(item.Invoice__c);
        inv.Total__c += (item.Cost__c * subtract);
    }
    update updateMap.values();
}

ShippingDiscount 触发器与测试类

Discount触发器

ShippingDiscount 触发器:在 Invoice 插入前判断总额是否超过阈值(如 100)——超过则应用运费折扣(设置 ShippingDiscount__c 字段)。示例展示条件业务逻辑在 before insert 中的最佳放置位置——在记录保存前修改值。

Test 类验证以下操作成功完成:

  • 插入 Line Items——验证 Invoice 总额正确计算
  • 更新 Line Items——验证总额重新计算
  • 删除 Line Items——验证总额减去已删除项
  • 应用运费折扣——验证 ShippingDiscount 正确设置
  • 负向测试——坏输入验证(如 null 成本/负数量)

测试类使用 @isTest 注解——使用 @testSetup 创建共享测试数据(Invoice + Line Items 基础数据)。每个测试方法验证一个特定用例——确保清晰的失败原因。使用 Test.startTest()/stopTest() 控制执行边界和 Governor Limit 重置。

应用架构与最佳实践总结

最佳实践总结

Shipping Invoice 应用展示的核心模式:

  • 触发器处理逻辑分离——触发器只做最小工作(收集 ID → 调用 handler 类方法)。Handler 类包含所有业务逻辑——便于测试和复用
  • 批量处理——所有触发器代码设计为处理多条记录。使用 Map/Set 组织数据——减少 SOQL 查询和 DML 语句
  • 测试覆盖所有场景——插入/更新/删除 + 正向/负向 + 单条/批量。触发器 + 类 + 测试 = 完整的质量保证
  • 使用事务边界——DML 操作在单一事务中——任何步骤失败全部回滚。触发器内的异常阻止操作完成
  • Governor Limit 意识——使用 Map 缓存查询结果避免 SOQL 循环。批量 DML(update updateMap.values())vs 逐条 update

恭喜你完成了全部 32 章的 Apex Developer Guide 学习之旅!从入门概念到高级集成和测试,这套完整的知识体系将支持你构建健壮、可扩展、可维护的 Salesforce 应用。