为 Apex 测试创建测试数据
学习目标
完成本单元后,您将能够:
- 创建测试实用程序类。
- 使用测试实用程序方法为各种测试个案建立测试数据。
- 在同一个类中执行所有测试方法。
为 Apex 测试创建测试数据
使用测试实用程序类为建立测试数据添加可重用的方法。
先决条件
如果您还未完成上一个单元的先决条件,即测试 Apex 触发器,请先完成。
添加测试实用程序类
通过调用实用程序类方法替换创建的测试数据,以重构之前的测试方法。首先,您需要创建测试实用程序类。
TestDataFactory
类是一种特殊的类 — 它是一个用 @isTest
注释的公共类,只能从正在运行的测试中访问。测试实用程序类包含测试方法可以调用的方法,用来执行实用的任务,例如建立测试数据。测试实用程序类不受组织的代码大小限制。
添加 TestDataFactory
类:
- 在 Developer Console 中,单击 File(文件)| New(新建)| Apex Class(Apex 类),并输入
TestDataFactory
作为类名,然后单击 OK(确定)。 - 将默认类主体替换为以下内容。
@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 语句,实现在单次调用中为所有客户创建集合中的所有业务机会。
最后,该方法返回新客户列表。
调用实用程序方法,创建测试数据
现在您已经添加了测试实用程序类,请修改 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
类中运行了测试,您只需重新运行此测试类即可运行其所有测试方法。
- 要执行相同的测试,请单击 Tests(测试)选项卡,选择您的测试运行,然后依次单击 Test(测试)| Rerun(重新运行)。
- 通过展开最新的测试运行,检查 Tests(测试)选项卡中的结果。测试运行应该报告所有四个测试都已通过!
资源