Skip to main content

为 Apex 测试创建测试数据

学习目标

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

  • 创建测试实用程序类。
  • 使用测试实用程序方法为各种测试个案建立测试数据。
  • 在同一个类中执行所有测试方法。
备注

备注

用中文(简体)学习?在中文(简体)Trailhead Playground 中开始挑战,用括号中提供的译文完成挑战。仅复制并粘贴英文值,因为挑战验证基于英文数据。如果在中文(简体)组织中没有成功通过挑战,我们建议您 (1) 将区域设置切换为美国,(2) 按此处说明将语言切换为英文,(3) 再次单击“检查挑战”按钮。

查看 Trailhead 本地化语言徽章详细了解如何利用 Trailhead 译文。

为 Apex 测试创建测试数据

使用测试实用程序类为建立测试数据添加可重用的方法。

先决条件

如果您还未完成上一个单元的先决条件,即测试 Apex 触发器,请先完成。

添加测试实用程序类

通过调用实用程序类方法替换创建的测试数据,以重构之前的测试方法。首先,您需要创建测试实用程序类。

TestDataFactory 类是一种特殊的类 — 它是一个用 @isTest 注释的公共类,只能从正在运行的测试中访问。测试实用程序类包含测试方法可以调用的方法,用来执行实用的任务,例如建立测试数据。测试实用程序类不受组织的代码大小限制。

添加 TestDataFactory 类:

  1. 在 Developer Console 中,单击 File(文件)| New(新建)| Apex Class(Apex 类),并输入 TestDataFactory 作为类名,然后单击 OK(确定)
  2. 将默认类主体替换为以下内容。
    @isTest
    public class TestDataFactory {
      public static List<Account> createAccountsWithOpps(Integer numAccts, Integer numOppsPerAcct) {
        List<Account> accts = new List<Account>();
        for(Integer i=0;i<numAccts;i++) {
          Account a = new Account(Name='TestAccount' + i);
          accts.add(a);
        }
        insert accts;
        List<Opportunity> opps = new List<Opportunity>();
        for(Integer j=0;j<numAccts;j++) {
          Account acct = accts[j];
          // For each account just inserted, add opportunities
          for(Integer k=0;k<numOppsPerAcct;k++) {
            opps.add(new Opportunity(Name=acct.Name + ' Opportunity ' + k,
              StageName='Prospecting',
              CloseDate=System.today().addMonths(1),
              AccountId=acct.Id));
          }
        }
        // Insert all opportunities for all accounts.
        insert opps;
        return accts;
      }
    }

此测试实用程序类包含一种静态方法 createAccountsWithOpps(),该方法接受 numAccts 参数中持有的客户数量以及 numOppsPerAcct 参数中为每一个客户创建的关联业务机会。该方法中的第一个循环创建了指定数量的客户,并将其保存在 accts 列表变量中。在第一个循环之后,调用 insert() DML 语句以创建数据库列表中的所有客户。

通过第二个循环创建了业务机会。由于每组业务机会都链接至同一个客户,所以外循环遍历了所有客户,并包含为当前客户创建相关业务机会的嵌套循环。下次运行嵌套循环时,使用 add() 方法将业务机会添加到同一个列表中。通过 AccountId 字段将业务机会链接至其父客户。创建的所有业务机会总数是业务机会数量与客户数量的乘积 (numOppsPerAcct*numAccts)。接下来,在循环外有效调用 insert() DML 语句,实现在单次调用中为所有客户创建集合中的所有业务机会。

最后,该方法返回新客户列表。

备注

即使该方法不返回关联的业务机会,您仍然可以通过编写 SOQL 查询来获取这些记录,该查询利用了客户和业务机会之间的现有关系,例如 测试 Apex 触发器中触发器使用的查询。

调用实用程序方法,创建测试数据

现在您已经添加了测试实用程序类,请修改 TestAccountDeletion 测试类以使用这个类。TestDataFactory.createAccountsWithOpps(1,1) 调用返回的数组包含一个客户 sObject。

这是修改后的测试方法。更精简的版本!

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    System.assert(!result.isSuccess());

    System.assert(result.getErrors().size() > 0);

    System.assertEquals('Cannot delete account with related opportunities.',

      result.getErrors()[0].getMessage());

  }

}

测试不同条件

一种测试方法不足以测试触发器所有可能的输入。我们需要测试一些其他条件,例如删除没有业务机会的客户时。我们还需要使用大量记录而不是单个记录来测试相同的场景。以下是包含三个附加测试方法的新版测试类。保存更新版本的类。

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    System.assert(!result.isSuccess());

    System.assert(result.getErrors().size() > 0);

    System.assertEquals('Cannot delete account with related opportunities.',

      result.getErrors()[0].getMessage());

  }

  @isTest

  static void TestDeleteAccountWithNoOpportunities() {

    // Test data setup

    // Create one account with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion was successful

    System.assert(result.isSuccess());

  }

  @isTest

  static void TestDeleteBulkAccountsWithOneOpportunity() {

    // Test data setup

    // Create accounts with one opportunity each by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // Verify for each record.

    // In this case the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    for(Database.DeleteResult dr : results) {

      System.assert(!dr.isSuccess());

      System.assert(dr.getErrors().size() > 0);

      System.assertEquals('Cannot delete account with related opportunities.',

        dr.getErrors()[0].getMessage());

    }

  }

  @isTest

  static void TestDeleteBulkAccountsWithNoOpportunities() {

    // Test data setup

    // Create accounts with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // For each record, verify that the deletion was successful

    for(Database.DeleteResult dr : results) {

      System.assert(dr.isSuccess());

    }

  }

}

运行所有测试方法

最后一步是在测试类中运行测试方法,现在该类包含了更全面的测试,并已重构为使用测试数据工厂。您已经在 TestAccountDeletion 类中运行了测试,您只需重新运行此测试类即可运行其所有测试方法。

  1. 要执行相同的测试,请单击 Tests(测试)选项卡,选择您的测试运行,然后依次单击 Test(测试)| Rerun(重新运行)
  2. 通过展开最新的测试运行,检查 Tests(测试)选项卡中的结果。测试运行应该报告所有四个测试都已通过!

资源

在 Salesforce 帮助中分享 Trailhead 反馈

我们很想听听您使用 Trailhead 的经验——您现在可以随时从 Salesforce 帮助网站访问新的反馈表单。

了解更多 继续分享反馈