如何为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
相关产品推荐
相关产品推荐

