Apex 测试(2)

学习目标

完成本单元后,您将能够:

  • 编写对单个记录操作触发的触发器的测试。
  • 执行一个类中的所有测试方法。

测试Apex 触发器

在部署触发器之前,编写单元测试以执行触发触发器的操作并验证预期的结果。
让我们测试一下我们之前在Writing Apex Triggers单元中使用的触发器。如果一个客户记录有相关的机会,AccountDeletion触发器将阻止记录的删除。

先决条件

  1. 如果您尚未添加AccountDeletion触发器,请按照下列步骤操作。
    1. 在开发者控制台中,点击File | New | Apex Trigger.
    2. 输入AccountDeletion作为触发器名称,然后选择sObject的Account。点击Submit.
    3. 用下面的代码替换默认的代码。
      trigger AccountDeletion on Account (before delete) {
         
          // 如果他们有相关的联系人,防止删除帐户。
          for (Account a : [SELECT Id FROM Account
                           WHERE Id IN (SELECT AccountId FROM Opportunity) AND
                           Id IN :Trigger.old]) {
              Trigger.oldMap.get(a.Id).addError(
                  '不能删除有相关机会的帐号');
          }
          
      }
  2. 如果您在之前的单元中添加了AccountDeletion触发器,但已将其禁用,以便系统可以检查您的挑战,请重新启用它。
    1. 从设置中搜索 Apex Triggers.
    2. 在Apex触发器页面上,单击AccountDeletion触发器旁边的Edit
    3. 选择Is Active.
    4. 点击Save.
  3. 如果您的组织包含以前的单元(称为AddRelatedRecord,CalloutTrigger或HelloWorldTrigger)的触发器,请禁用它们。例如,要禁用AddRelatedRecord触发器:
    1. 从设置中搜索 Apex Triggers.
    2. 在Apex触发器页面上,单击AddRelatedRecord触发器旁边的 Edit .
    3. 取消选择Is Active.
    4. 点击Save.
  4. 要禁用HelloWorldTrigger和CalloutTrigger触发器,请重复上述步骤。

添加和运行单元测试

首先,我们开始添加一个测试方法。这个测试方法验证触发器设计要做什么(正面情况):防止一个帐户被删除,如果它有相关的机会。

  1. 在开发者控制台中,点击 File | New | Apex Class.
  2. 输入TestAccountDeletion作为类名称,然后单击 OK.
  3. 用下面的代码替换默认的类体。
    @isTest
    private class TestAccountDeletion {
    
        @isTest static void TestDeleteAccountWithOneOpportunity() {
            // 测试数据设置
            // 创建一个有机会的帐户,然后尝试删除它
            Account acct = new Account(Name='Test Account');
            insert acct;
            Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                           StageName='Prospecting',
    CloseDate=System.today().addMonths(1),
                                           AccountId=acct.Id);
            insert opp;
            
            // 执行测试
            Test.startTest();
            Database.DeleteResult result = Database.delete(acct, false);
            Test.stopTest();
    
            // 验证
            // 在这种情况下,删除应该已经被触发器停止,
            // 确认我们收到了错误
            System.assert(!result.isSuccess());
            System.assert(result.getErrors().size() > 0);
            System.assertEquals('不能删除有相关机会的帐户',
                                 result.getErrors()[0].getMessage());
        }
        
    }

    测试方法首先建立一个机会的测试帐户。接下来,它将删除测试帐户,该帐户触发AccountDeletion触发器。测试方法通过检查Database.delete()调用的返回值来验证触发器是否阻止删除测试帐户。返回值是一个Database.DeleteResult对象,其中包含有关删除操作的信息。测试方法验证删除不成功并验证获得的错误消息。

  4. 要运行此测试,请单击 Test | New Run.
  5. 在Test Classes下,单击TestAccountDeletion。
  6. 要将TemperatureConverterTest类中的所有方法添加到测试运行中,请单击添加 Add Selected.
  7. 点击Run.

    在最新运行的“测试”选项卡中找到测试结果。

TestAccountDeletion测试类只包含一个测试方法,用于测试单个帐户记录。此外,这个测试是针对正面的情况。始终测试更多方案,以确保触发器在所有情况下都能正常工作,包括删除没有机会的帐户和批量帐户删除。

测试数据是在测试方法内部设置的,添加更多的测试方法会耗费时间。如果您有许多测试方法,请将测试数据创建放在测试实用程序类中,并从多个测试方法中调用该实用程序类。下一个单元将向您展示如何利用测试工具类并添加更多的测试方法。

告诉我更多

测试方法包含Test.startTest()和Test.stopTest()方法对,该方法对代码块进行分隔,得到一组新的控制器限制。 在此测试中,测试数据设置在执行测试之前使用两个DML语句。 要测试Apex代码在限速范围内运行,请将数据设置的限制使用与测试隔离。 要隔离数据设置过程的限制使用,请将测试调用包含在Test.startTest()和Test.stopTest()块中。 测试异步Apex时也使用此测试块。 有关更多信息,请参阅使用限制,startTest和stopTest。

注意

开发人员控制台的一个已知问题是,在运行测试子集时,无法正确更新代码覆盖率。 要更新代码覆盖率结果,请使用 Test | Run All 而不是Test | New Run.