为 Apex 测试创建测试数据
学习目标
完成本单元后,您将能够:
- 创建测试实用程序类。
- 使用测试实用程序方法为各种测试个案建立测试数据。
- 在同一个类中执行所有测试方法。
- 使用测试实用程序类为建立测试数据添加可重用的方法。
先决条件
如果您还未完成上一个单元的先决条件,即测试 Apex 触发器,请先完成。
添加测试实用程序类
通过调用实用程序类方法替换创建的测试数据,以重构之前的测试方法。首先,您需要创建测试实用程序类。
TestDataFactory 类是一个用 @IsTest 注释的公共类,只能从正在运行的测试中访问。测试实用程序类包含测试方法可以调用的方法,用来执行实用的任务,例如建立测试数据。测试实用程序类不受组织的代码大小限制。
添加 TestDataFactory 类:
- 在 Web Console(Web 控制台)中,按 Ctrl+Shift+P (Windows) 或 ⌘+Shift+P (macOS) 打开命令面板。
- 输入
SFDX: Create Apex Class(SFDX:创建 Apex 类),然后按 Enter 键。
- 对于模板类型,请选择 DefaultApexClass,然后按 Enter 键。
- 对于类名称,请输入
TestDataFactory,然后按 Enter 键。
- 对于输出目录,请选择 force-app/main/default/classes,然后按 Enter 键。
- 将默认类主体替换为以下内容。
@IsTest
public with sharing 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 as user 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 as user opps;
return accts;
}
}此测试实用程序类包含一种静态方法 createAccountsWithOpps(),该方法接受 numAccts 参数中持有的客户数量以及 numOppsPerAcct 参数中为每一个客户创建的关联业务机会。该方法中的第一个循环创建了指定数量的客户,并将其保存在 accts 列表变量中。在第一个循环之后,调用 insert DML 语句以创建数据库列表中的所有客户。
通过第二个循环创建了业务机会。由于每组业务机会都链接至同一个客户,所以外循环遍历了所有客户,并包含为当前客户创建相关业务机会的嵌套循环。下次运行嵌套循环时,使用 add() 方法将业务机会添加到同一个列表中。通过 AccountId 字段将业务机会链接至其父客户。创建的所有业务机会总数是业务机会数量与客户数量的乘积 (numOppsPerAcct*numAccts)。接下来,在循环外有效调用 insert DML 语句,实现在单次调用中为所有客户创建集合中的所有业务机会。
最后,该方法返回新客户列表。
调用实用程序方法,创建测试数据
现在您已经添加了测试实用程序类,请修改 TestAccountDeletion 测试类以使用这个类。TestDataFactory.createAccountsWithOpps(1,1) 调用返回的数组包含一个客户 sObject。
这是修改后的测试方法。
@IsTest
private with sharing 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, AccessLevel.USER_MODE);
Test.stopTest();
// Verify that the deletion should have been stopped by the trigger,
// so check that we got back an error.
Assert.isFalse(result.isSuccess());
Assert.isTrue(result.getErrors().size() > 0);
Assert.areEqual('Cannot delete account with related opportunities.',
result.getErrors()[0].getMessage());
}
}测试不同条件
一种测试方法不足以测试触发器所有可能的输入。我们需要测试一些其他条件,例如删除没有业务机会的客户时。我们还需要使用大量记录而不是单个记录来测试相同的场景。以下是包含三个附加测试方法的新版测试类。保存更新版本的类。
@IsTest
private with sharing 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, AccessLevel.USER_MODE);
Test.stopTest();
// Verify that the deletion should have been stopped by the trigger,
// so check that we got back an error.
Assert.isFalse(result.isSuccess());
Assert.isTrue(result.getErrors().size() > 0);
Assert.areEqual('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, AccessLevel.USER_MODE);
Test.stopTest();
// Verify that the deletion was successful
Assert.isTrue(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, AccessLevel.USER_MODE);
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) {
Assert.isFalse(dr.isSuccess());
Assert.isTrue(dr.getErrors().size() > 0);
Assert.areEqual('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, AccessLevel.USER_MODE);
Test.stopTest();
// For each record, verify that the deletion was successful
for(Database.DeleteResult dr : results) {
Assert.isTrue(dr.isSuccess());
}
}
}运行所有测试方法
最后一步是在测试类中运行测试方法,现在该类包含了更全面的测试,并已重构为使用测试数据工厂。
- 在 Web Console(Web 控制台)中,点击 Activity Bar(活动栏)中的
。Testing(测试)侧面板随即打开。
- 在 Testing(测试)搜索栏中,输入
TestAccountDeletion。
- 要运行类中的所有测试方法,将鼠标悬停在 TestAccountDeletion 行上,然后点击
。
- 在 Test Results(测试结果)面板中查看结果。测试运行应该报告所有四个测试都已通过!
资源
