You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Account更新触发器编写对应的Apex测试类

Account触发器助手类测试类编写方案

核心测试场景覆盖

  • 验证Account的AccountSource/Account_Sub_Source__c字段修改后,关联Opportunity对应字段同步更新的正向逻辑
  • 验证Account其他字段修改时,关联Opportunity对应字段不会被误修改的反向逻辑
  • 验证批量更新场景下的代码执行稳定性,避免 governor limit 报错

完整测试类代码

@isTest
private class AccountTiggerHelperTest {
    // 测试初始化数据,统一创建测试用Account和关联Opportunity
    @testSetup
    static void createTestData() {
        // 创建测试Account
        Account testAcc = new Account(
            Name = '测试客户',
            AccountSource = '官网',
            Account_Sub_Source__c = '百度推广'
        );
        insert testAcc;

        // 创建关联的测试Opportunity
        Opportunity testOpp = new Opportunity(
            Name = '测试商机',
            AccountId = testAcc.Id,
            StageName = '需求沟通',
            CloseDate = Date.today().addMonths(1),
            LeadSource = '线下活动',
            Lead_Sub_Source__c = '展会'
        );
        insert testOpp;
    }

    // 测试正向场景:修改Account来源字段,Opp同步更新
    @isTest
    static void testUpdateOppWhenAccSourceChange() {
        // 取出测试数据
        Account testAcc = [SELECT Id, AccountSource, Account_Sub_Source__c FROM Account WHERE Name = '测试客户' LIMIT 1];
        Opportunity oldOpp = [SELECT Id, LeadSource, Lead_Sub_Source__c FROM Opportunity WHERE AccountId = :testAcc.Id LIMIT 1];
        // 先记录修改前的Opp字段值
        String oldLeadSource = oldOpp.LeadSource;
        String oldSubSource = oldOpp.Lead_Sub_Source__c;

        Test.startTest();
        // 修改Account的两个来源字段
        testAcc.AccountSource = '第三方推荐';
        testAcc.Account_Sub_Source__c = '合作伙伴转介绍';
        Map<Id, Account> oldAccMap = new Map<Id, Account>([SELECT Id, AccountSource, Account_Sub_Source__c FROM Account WHERE Id = :testAcc.Id]);
        update testAcc;
        // 若单独测试助手类可直接调用:AccountTiggerHelper.UpdateOpportunityLeadSourceThroughAccount(new List<Account>{testAcc}, oldAccMap);
        Test.stopTest();

        // 断言验证Opp字段已同步更新
        Opportunity updatedOpp = [SELECT Id, LeadSource, Lead_Sub_Source__c FROM Opportunity WHERE AccountId = :testAcc.Id LIMIT 1];
        System.assertEquals(testAcc.AccountSource, updatedOpp.LeadSource, 'Opportunity的LeadSource未同步更新');
        System.assertEquals(testAcc.Account_Sub_Source__c, updatedOpp.Lead_Sub_Source__c, 'Opportunity的Lead_Sub_Source__c未同步更新');
    }

    // 测试反向场景:修改Account非来源字段,Opp不更新
    @isTest
    static void testNoUpdateOppWhenAccOtherFieldChange() {
        Account testAcc = [SELECT Id, AccountSource, Account_Sub_Source__c, Name FROM Account WHERE Name = '测试客户' LIMIT 1];
        Opportunity oldOpp = [SELECT Id, LeadSource, Lead_Sub_Source__c FROM Opportunity WHERE AccountId = :testAcc.Id LIMIT 1];
        String oldLeadSource = oldOpp.LeadSource;
        String oldSubSource = oldOpp.Lead_Sub_Source__c;

        Test.startTest();
        // 只修改Account名称,不碰来源字段
        testAcc.Name = '测试客户修改后名称';
        Map<Id, Account> oldAccMap = new Map<Id, Account>([SELECT Id, AccountSource, Account_Sub_Source__c FROM Account WHERE Id = :testAcc.Id]);
        update testAcc;
        Test.stopTest();

        // 断言验证Opp字段没有被修改
        Opportunity updatedOpp = [SELECT Id, LeadSource, Lead_Sub_Source__c FROM Opportunity WHERE AccountId = :testAcc.Id LIMIT 1];
        System.assertEquals(oldLeadSource, updatedOpp.LeadSource, '修改Account非来源字段时错误更新了Opportunity的LeadSource');
        System.assertEquals(oldSubSource, updatedOpp.Lead_Sub_Source__c, '修改Account非来源字段时错误更新了Opportunity的Lead_Sub_Source__c');
    }

    // 测试批量场景
    @isTest
    static void testBatchUpdateScenario() {
        // 批量创建200个Account和对应Opp
        List<Account> accList = new List<Account>();
        for(Integer i=0; i<200; i++) {
            accList.add(new Account(
                Name = '批量客户' + i,
                AccountSource = '初始来源',
                Account_Sub_Source__c = '初始子来源'
            ));
        }
        insert accList;

        List<Opportunity> oppList = new List<Opportunity>();
        for(Account acc : accList) {
            oppList.add(new Opportunity(
                Name = '批量商机' + acc.Name,
                AccountId = acc.Id,
                StageName = '初步接触',
                CloseDate = Date.today().addMonths(2)
            ));
        }
        insert oppList;

        Test.startTest();
        // 批量修改所有Account的来源字段
        for(Account acc : accList) {
            acc.AccountSource = '批量修改后来源';
            acc.Account_Sub_Source__c = '批量修改后子来源';
        }
        Map<Id, Account> oldAccMap = new Map<Id, Account>(accList.deepClone(true, true, true));
        update accList;
        Test.stopTest();

        // 验证批量更新结果
        List<Opportunity> updatedOpps = [SELECT Id, LeadSource, Lead_Sub_Source__c, AccountId FROM Opportunity WHERE AccountId IN :accList];
        System.assertEquals(200, updatedOpps.size(), '关联商机数量不正确');
        for(Opportunity opp : updatedOpps) {
            System.assertEquals('批量修改后来源', opp.LeadSource);
            System.assertEquals('批量修改后子来源', opp.Lead_Sub_Source__c);
        }
    }
}

补充说明

  • 如果是要覆盖触发器的执行逻辑,直接在测试方法里update Account即可,不需要手动调用助手类方法,代码里两种调用方式都给了注释说明
  • 所有测试场景都加了明确的断言,确保逻辑符合预期,而不是只追求代码覆盖率
  • 批量场景测试可以验证代码不会触发SOQL、DML governor limit报错,适配实际业务的批量操作需求

内容的提问来源于stack exchange,提问作者sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 00:27:07