测试 Apex 触发器
学习目标
完成本单元后,您将能够:
- 为单个记录操作触发的触发器编写测试。
- 在同一个类中执行所有测试方法。
测试 Apex 触发器
在部署触发器之前,编写单元测试以执行触发触发器并验证预期结果的操作。
让我们来测试一个在 Apex 触发器模块中使用过的触发器。如果某个客户记录具有关联的业务机会,则 AccountDeletion
触发器会阻止删除该记录。
先决条件
如果您还未添加 AccountDeletion
触发器,请执行如下步骤。
- 在 Developer Console 中,单击 File(文件) | New(新建) | Apex Trigger(Apex 触发器)。
- 输入
AccountDeletion
作为触发器名称,然后为 sObject 选择 Account(客户)。单击提交。 - 将默认代码替换为以下内容。
trigger AccountDeletion on Account (before delete) { // Prevent the deletion of accounts if they have related opportunities. 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('Cannot delete account with related opportunities.'); } }
如果您在上一个单元中添加过 AccountDeletion
触发器,但已禁用了该触发器以便系统检测您的挑战,请重新启用该触发器。
- 在 Setup(设置)中,搜索
Apex Triggers
(Apex 触发器)。 - 在 Apex Triggers(Apex 触发器)页面中,单击
AccountDeletion
触发器旁边的 Edit(编辑)。 - 选择 Is Active(有效)。
- 单击保存。
如果组织中包含上一个单元创建的 AddRelatedRecord
、CalloutTrigger
或 HelloWorldTrigger
触发器,请禁用这些触发器。例如,要禁用 AddRelatedRecord
触发器,请执行以下操作:
- 在 Setup(设置)中,搜索
Apex Triggers
(Apex 触发器)。 - 在 Apex Triggers(Apex 触发器)页面中,单击
AddRelatedRecord
触发器旁边的 Edit(编辑)。 - 取消选择 Is Active(有效)。
- 单击保存。
重复前面的步骤,禁用 HelloWorldTrigger
和 CalloutTrigger
触发器。
添加并运行单元测试
首先,让我们从添加一个测试方法开始。此测试方法验证触发器的设计目标(正向用例):防止客户在拥有关联业务机会时被删除。
- 在 Developer Console 中,单击 File(文件)| New(新建)| Apex Class(Apex 类)。
- 输入
TestAccountDeletion
作为类名称,然后单击 OK(确定)。 - 将默认类主体替换为以下内容。测试方法第一步是创建一个拥有业务机会的测试客户。然后,删除测试客户,该删除操作会触发
@isTest private class TestAccountDeletion { @isTest static void TestDeleteAccountWithOneOpportunity() { // Test data setup // Create an account with an opportunity, and then try to delete it 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; // Perform test Test.startTest(); Database.DeleteResult result = Database.delete(acct, false); Test.stopTest(); // Verify // In this case the deletion should have been stopped by the trigger, // so verify 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()); } }
AccountDeletion
触发器。测试方法通过检查Database.delete()
调用的返回值来验证触发器是否阻止删除测试客户。返回值是一个Database.DeleteResult
对象,其中包含有关删除操作的信息。测试方法验证删除不成功并验证获取的错误提示。 - 要运行该测试,请依次单击 Test(测试)| New Run(新运行)。
- 在 Test Classes(测试类)下方,单击 TestAccountDeletion。
- 要将
TestAccountDeletion
类中的所有测试方法添加到测试运行中,请单击 Add Selected(添加所选项)。 - 单击运行。在最新运行的 Tests(测试)选项卡中查找测试结果。
TestAccountDeletion
测试类只包含一个测试方法,用于测试单个客户记录。这同样也是正向用例的测试。测试更多场景以确保触发器适用于所有情况,包括删除没有业务机会的客户和批量删除客户。
测试数据是在测试方法内部设置的,当您添加更多测试方法时,这可能会很耗时。如果您有多种测试方法,请将创建的测试数据放在一个测试实用程序类中,并从多种测试方法中调用该实用程序类。下一个单元将向您展示如何利用测试实用程序类并添加更多的测试方法。
了解详细信息
测试方法包含 Test.startTest()
和 Test.stopTest()
方法对,用于界定获取一组新调控器限制的代码块。在该测试中,执行测试之前建立测试数据使用了两个 DML 语句。要测试 Apex 代码是否在调控器限制内运行,请将数据建立与测试的限制使用情况分离。要分离数据建立进程的限制使用情况,请将测试调用包含在 Test.startTest()
和 Test.stopTest()
块中。测试异步 Apex 时也使用该测试块。有关更多信息,请参见使用限制、startTest 以及 stopTest。
资源
准备好迎接实践挑战
为了完成本单元的实践挑战,您需要使用下面的代码在联系人对象上创建一个名为 RestrictContactByName
的 Apex 触发器:
trigger RestrictContactByName on Contact (before insert, before update) { //check contacts prior to insert or update for invalid data for(Contact c : Trigger.New) { if(c.LastName == 'INVALIDNAME') { //invalidname is invalid c.AddError('The Last Name "'+c.LastName+'" is not allowed for DML'); } } }