在 Salesforce Apex 中使用静态变量
Using static variables in Salesforce Apex
我们在测试 classes 中注意到一些有趣的行为,当使用静态变量来确保触发器只触发一次时。考虑以下触发器 class 和 testclass:
触发器:
trigger RecursiveTrigger on Account (before insert) {
if(RecursiveClass.RunOnce) {
RecursiveClass.RunOnce = false;
if(Trigger.isInsert) {
RecursiveClass.doStuffOnInsert();
}
if(Trigger.isUpdate) {
RecursiveClass.doStuffOnUpdate();
}
}
}
Class:
public class RecursiveClass {
public static boolean RunOnce = true;
public static void doStuffOnInsert() {}
public static void doStuffOnUpdate() {}
}
测试class:
@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();在触发器中将不会执行,因为静态变量似乎仍已设置。根据我在文档中阅读的内容,静态变量仅在整个事务中保存(即插入或更新)。测试 class 中的更新不会是一个全新的交易还是我误解了这一点?
我能够解决这个问题的唯一方法是将静态变量拆分为一个用于插入,一个用于更新。
这是因为两个 DML 语句 insert
和 update
是同一个 Apex 交易的一部分,以下摘录对其进行了很好的解释。
A static variable is static only within the scope of the Apex transaction. It’s not static across the server or the entire organization. The value of a static variable persists within the context of a single transaction and is reset across transaction boundaries. For example, if an Apex DML request causes a trigger to fire multiple times, the static variables persist across these trigger invocations.
你可以找到详细的例子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;
}
}
希望对您有所帮助。
你的测试应该看起来像
@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 可以让您了解用户的下一步操作。静态变量用于防止触发循环。就像,你更新了一个对象,然后在触发器中你做了一些操作,然后更新了这个对象。这可能会导致触发器更新无限循环。为了防止这种情况,使用了静态变量。
我们在测试 classes 中注意到一些有趣的行为,当使用静态变量来确保触发器只触发一次时。考虑以下触发器 class 和 testclass:
触发器:
trigger RecursiveTrigger on Account (before insert) {
if(RecursiveClass.RunOnce) {
RecursiveClass.RunOnce = false;
if(Trigger.isInsert) {
RecursiveClass.doStuffOnInsert();
}
if(Trigger.isUpdate) {
RecursiveClass.doStuffOnUpdate();
}
}
}
Class:
public class RecursiveClass {
public static boolean RunOnce = true;
public static void doStuffOnInsert() {}
public static void doStuffOnUpdate() {}
}
测试class:
@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();在触发器中将不会执行,因为静态变量似乎仍已设置。根据我在文档中阅读的内容,静态变量仅在整个事务中保存(即插入或更新)。测试 class 中的更新不会是一个全新的交易还是我误解了这一点?
我能够解决这个问题的唯一方法是将静态变量拆分为一个用于插入,一个用于更新。
这是因为两个 DML 语句 insert
和 update
是同一个 Apex 交易的一部分,以下摘录对其进行了很好的解释。
A static variable is static only within the scope of the Apex transaction. It’s not static across the server or the entire organization. The value of a static variable persists within the context of a single transaction and is reset across transaction boundaries. For example, if an Apex DML request causes a trigger to fire multiple times, the static variables persist across these trigger invocations.
你可以找到详细的例子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;
}
}
希望对您有所帮助。
你的测试应该看起来像
@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 可以让您了解用户的下一步操作。静态变量用于防止触发循环。就像,你更新了一个对象,然后在触发器中你做了一些操作,然后更新了这个对象。这可能会导致触发器更新无限循环。为了防止这种情况,使用了静态变量。