当前位置: 首页 > 知识库问答 >
问题:

在Salesforce Apex中使用静态变量

滑文昌
2023-03-14

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

触发:

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

我能够绕过这个问题的唯一方法是将静态变量拆分为一个用于插入,一个用于更新。

共有2个答案

黄流觞
2023-03-14

你的测试应该看起来像

@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可以让您了解用户的下一个操作。静态变量用于防止触发循环。比如,您更新了一个对象,然后在触发器中执行了一些操作,然后更新了这个对象。这可能会导致触发器更新的无限循环。为了防止这种情况,使用了静态变量。

钱星辰
2023-03-14

之所以会发生这种情况,是因为两条DML语句insert和update是同一Apex事务的一部分,下面的摘录对此进行了很好的解释。

静态变量仅在Apex事务的范围内是静态的。它不是跨服务器或整个组织的静态变量。静态变量的值在单个事务的上下文中持久存在,并跨事务边界重置。例如,如果Apex DML请求导致触发器多次触发,则静态变量在这些触发器调用中持续存在。

你可以在这里找到一个详细的例子。

编辑:

还有一件事,您需要更新触发器以处理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;
   }
}

希望这有帮助。

 类似资料:
  • 问题内容: 在android中,推荐使用静态变量吗?例如,用Java实现Singleton模式,我通常这样做: 此外,Android JVM何时可以清除此漏洞? 问题答案: 字段会整体附加到实例,而实例又附加到加载了类的。整个回收时将被卸载。我确信这会在销毁该应用程序时发生(不是在它进入后台或暂停但完全关闭时发生)。 因此,只要你的应用程序运行,就可以将其视为生存。Singleton是个好主意吗?

  • 问题内容: 我正在使用spring的PreAuthorize注释,如下所示: 但是,我已经在另一个类上将“角色”定义为静态字符串。如果我尝试使用此值: 我收到一个错误: 有没有办法使用PreAuthorize批注访问此类静态变量? 问题答案: 尝试以下使用Spring Expression Language评估类型的方法: 确保指定完全限定的类名。 文献资料

  • 我不知道什么时候在程序中使用一个静态/非静态变量。 我理解非静态/静态变量之间的区别,但我只是不知道何时使用每一个变量。那么在上面的代码中,为什么函数不能是静态的呢?(什么时候应该是静态的?)

  • 问题内容: 说我有两个这样的课程: 在两个实例都被多次实例化并且这两个类的实例的方法被大量调用的情况下,使用在A类中持有的静态变量而不是在其中使用任何 实际的 优点/缺点(时间,内存)在每个单独的实例中创建一个新对象,例如在类B中? 该应用程序是多线程的,并且具有更高的随机性,因此我认为我要使用static 。如果在分析后这将是一个真正的速度因素,我可能会选择其他东西。 问题答案: 实际的 优缺点

  • 问题内容: 我已经定义了一个对象并声明了一个静态变量。在该方法中,当我尝试打印实例和类变量时,两者都打印相同的值。 不是实例变量吗?它应该打印0而不是50吗? 问题答案: 不,只有一个变量-您尚未声明任何实例变量。 不幸的是,Java允许您访问静态成员,就像通过相关类型的引用访问静态成员一样。这是IMO的设计缺陷,某些IDE(例如Eclipse)允许您将其标记为警告或错误- 但这是语言的一部分。您

  • 问题内容: 我想要以下设置: 这在Java中可能吗?怎么样?如果可以避免的话,我宁愿不使用实例变量/方法。 谢谢! 编辑: 常量是数据库表的名称。每个子对象都是一个微型ORM。 问题答案: 您无法完全按照自己的意愿去做。也许可以接受的折衷方案是: