学习目标
完成本单元后,您将能够:
- 创建一个测试工具类。
- 使用测试实用程序方法为各种测试用例设置测试数据。
- 执行一个类中的所有测试方法。
为Apex测试创建测试数据
先决条件
如果您还没有这样做,请完成上一个单元“测试Apex触发器”中的先决条件。
添加一个测试工具类
让我们通过用一个实用程序类方法的调用替换测试数据创建来重构以前的测试方法。首先,您需要创建测试实用程序类。
TestDataFactory类是一种特殊的类,它是一个公共类,它是用isTest注释的,只能从正在运行的测试中访问。测试工具类包含可以被测试方法调用来执行有用任务的方法,例如设置测试数据。测试工具类从组织的代码大小限制中排除。
要添加TestDataFactory类:
- 在开发者控制台中,点击 , 然后输入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 (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 opps; return accts; } }
第二个循环创造了机会。由于每个机会组都链接到一个客户,所以外部循环通过客户进行迭代,并包含一个嵌套的循环,为当前客户创建相关的机会。下次运行嵌套循环时,使用add()方法将机会添加到同一个列表中。使用AccountId字段将机会链接到其父帐户。创建的所有机会总数是机会数量与客户数量的乘积(numOppsPerAcct * numAccts)。接下来,在循环之外有效地调用insert()DML语句,以便仅在一个调用中为所有帐户创建集合中的所有机会。
最后,这个方法返回新帐户的列表。
调用测试数据创建的实用程序方法
现在您已经添加了测试实用程序类,请修改测试类以利用此类。在TestAccountDeletion类中,替换以// Test data setup开始的块,并以insert opp结束:
// 测试数据设置
// 通过调用实用程序方法创建一个拥有一个机会的帐户
Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);
这是修改后的测试方法。更短的版本!
@isTest
private class TestAccountDeletion {
@isTest static void TestDeleteAccountWithOneOpportunity() {
// 测试数据设置
// 通过调用实用程序方法创建一个拥有一个机会的帐户
Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);
// 执行测试
Test.startTest();
Database.DeleteResult result = Database.delete(accts[0], false);
Test.stopTest();
// 验证删除是否应该被触发器停止,
// 检查我们是否收到错误
System.assert(!result.isSuccess());
System.assert(result.getErrors().size() > 0);
System.assertEquals('不能删除有相关机会的帐户.',
result.getErrors()[0].getMessage());
}
}
测试不同的条件
一种测试方法不足以测试触发器的所有可能输入。我们需要测试一些其他条件,例如何时删除没有机会的客户。我们还需要使用批量数量的记录来测试相同的方案,而不是只记录一个记录。这里是包含三个附加测试方法的测试类的更新版本。保存此类更新的版本。
@isTest
private class TestAccountDeletion {
@isTest static void TestDeleteAccountWithOneOpportunity() {
// 测试数据设置
// 通过调用实用程序方法创建一个拥有一个机会的帐户
Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);
// Perform test
Test.startTest();
Database.DeleteResult result = Database.delete(accts[0], false);
Test.stopTest();
// 验证删除是否应该被触发器停止,
// 检查我们是否收到错误
System.assert(!result.isSuccess());
System.assert(result.getErrors().size() > 0);
System.assertEquals('不能删除有相关机会的帐户',
result.getErrors()[0].getMessage());
}
@isTest static void TestDeleteAccountWithNoOpportunities() {
// 测试数据设置
// 通过调用实用程序方法创建一个没有机会的帐户
Account[] accts = TestDataFactory.createAccountsWithOpps(1,0);
// 执行测试
Test.startTest();
Database.DeleteResult result = Database.delete(accts[0], false);
Test.stopTest();
//验证删除是否成功
System.assert(result.isSuccess());
}
@isTest static void TestDeleteBulkAccountsWithOneOpportunity() {
// 测试数据设置
// 通过调用一个实用程序方法创建每个客户
Account[] accts = TestDataFactory.createAccountsWithOpps(200,1);
// 执行测试
Test.startTest();
Database.DeleteResult[] results = Database.delete(accts, false);
Test.stopTest();
// 验证每个记录。
// 在这种情况下,删除应该已经被触发器停止,
// 检查我们是否收到错误
for(Database.DeleteResult dr : results) {
System.assert(!dr.isSuccess());
System.assert(dr.getErrors().size() > 0);
System.assertEquals('不能删除有相关机会的帐户',
dr.getErrors()[0].getMessage());
}
}
@isTest static void TestDeleteBulkAccountsWithNoOpportunities() {
// 测试数据设置
// 通过调用实用程序方法创建没有机会的帐户
Account[] accts = TestDataFactory.createAccountsWithOpps(200,0);
// 执行测试
Test.startTest();
Database.DeleteResult[] results = Database.delete(accts, false);
Test.stopTest();
// 对于每条记录,验证删除是否成功
for(Database.DeleteResult dr : results) {
System.assert(dr.isSuccess());
}
}
}
最后一步是在我们的测试类中运行测试方法,现在该类包含更全面的测试,并被重构为使用测试数据工厂。由于您已经在TestAccountDeletion类中运行了测试,因此您可以重新运行此测试类以运行其所有测试方法。
- .
- 通过展开最新的测试运行来检查“测试”选项卡中的结果。测试运行应报告所有四个测试通过!