在 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 语句 insertupdate 是同一个 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 可以让您了解用户的下一步操作。静态变量用于防止触发循环。就像,你更新了一个对象,然后在触发器中你做了一些操作,然后更新了这个对象。这可能会导致触发器更新无限循环。为了防止这种情况,使用了静态变量。