【问题标题】:Using static variables in Salesforce Apex在 Salesforce Apex 中使用静态变量
【发布时间】:2016-02-15 10:56:15
【问题描述】:

当使用静态变量来确保触发器只触发一次时,我们注意到测试类中有一些有趣的行为。考虑以下触发器、类和测试类:

触发器:

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() {}
}

测试类:

@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();在触发器中不会执行,因为静态变量似乎仍然被设置。根据我在文档中阅读的内容,静态变量仅在整个事务中保存(即插入或更新)。测试类中的更新不会是全新的事务还是我误解了这一点?

我能够解决这个问题的唯一方法是将静态变量分为一个用于插入和一个用于更新。

【问题讨论】:

    标签: variables static salesforce apex


    【解决方案1】:

    这是因为两个 DML 语句 insertupdate 是同一个 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;
       }
    }
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的快速回复!有没有办法在测试类中进行单独的事务?如果我们使用的是自给自足的测试方法(SeeAllData=false),我想插入一些帐户,而不是查询数据库并更新它们。
    • 该更新在我的真实代码中,但在我的示例中忘记了 :) 感谢您的回答!
    • RecursiveClass.RunOnce = true;在触发器运行之前不要执行。 while(Trigger.isExecuting);中不需要了
    • @Chiz 感谢您的洞察力。我已经更新了我的答案。
    【解决方案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 可以让您了解用户的下一步操作。静态变量用于防止触发循环。就像,你更新了一个对象,然后在触发器中你做了一些操作,然后更新了这个对象。这可能会导致触发器更新的无限循环。为了防止这种静态变量被使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2011-01-29
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多