我们在测试类中注意到一些有趣的行为,当使用静态变量来确保触发器只触发一次。考虑以下触发器,类和测试类:
触发:
trigger RecursiveTrigger on Account (before insert) {
if(RecursiveClass.RunOnce) {
RecursiveClass.RunOnce = false;
if(Trigger.isInsert) {
RecursiveClass.doStuffOnInsert();
}
if(Trigger.isUpdate) {
RecursiveClass.doStuffOnUpdate();
}
}
}
类别:
public class RecursiveClass {
public static boolean RunOnce = true;
public static void doStuffOnInsert() {}
public static void doStuffOnUpdate() {}
}
识别TestClass:
@IsTest(SeeAllData=false)
public class TestRecursiveClass {
static testMethod void testAccountInsertUpdate() {
Account a = new Account(Name = 'Testing Recursive');
insert a;
a.Name = 'Testing Update';
update a;
}
}
基于此,我希望100%的代码覆盖率,但当你运行它时,行RecursiveClass.doStuffOnUpdate();在触发器中将不会执行,因为静态变量似乎仍然设置。根据我在文档中读到的内容,静态变量仅在整个事务中保存(即插入或更新)。测试类中的更新不是一个全新的事务,还是我误解了这个?
我能解决这个问题的唯一方法是将静态变量分为一个用于插入,一个用于更新。
答案 0 :(得分:3)
这是因为两个DML语句insert
update
是同一个Apex交易的一部分,以下摘录解释得很清楚。
静态变量仅在Apex事务的范围内是静态的。它在整个服务器或整个组织中都不是静态的。静态变量的值在单个事务的上下文中保留,并在事务边界之间重置。例如,如果Apex DML请求导致触发器多次触发,则静态变量会在这些触发器调用中持续存在。
您可以找到有关它的详细示例here。
修改强>
还有一件事,您需要更新触发器以处理update
以及
trigger RecursiveTrigger on Account(before insert, before update) {
}
修改强>
而且,以下是如何达到100%覆盖率
@IsTest(SeeAllData=false)
public class TestRecursiveClass {
static testMethod void testAccountInsertUpdate() {
Account a = new Account(Name = 'Testing Recursive');
insert a;
RecursiveClass.RunOnce = true;
a.Name = 'Testing Update';
update a;
}
}
希望这有帮助。
答案 1 :(得分:2)
您的测试应该是
@IsTest(SeeAllData=false)
public class TestRecursiveClass {
static testMethod void testAccountInsertUpdate() {
Account a = new Account(Name = 'Testing Recursive');
insert a;
a.Name = 'Testing Update';
RecursiveClass.RunOnce = true;
update a;
}
}
在下一个DML之前将静态变量设置为true可让您了解用户的下一步操作。静态变量用于防止触发循环。就像,你更新了一个对象,然后在触发器中你做了一些操作,然后更新了这个对象。这可能导致无限循环的触发更新。为了防止使用这个静态变量。