2016-02-15 1 views
0

Nous avons remarqué un comportement intéressant dans nos classes de test lorsque vous utilisez des variables statiques pour vous assurer que les déclencheurs se déclenchent une seule fois. Considérez le déclencheur suivant, la classe et testclass:Utilisation de variables statiques dans Salesforce Apex

Trigger:

trigger RecursiveTrigger on Account (before insert) { 

    if(RecursiveClass.RunOnce) { 
     RecursiveClass.RunOnce = false; 
     if(Trigger.isInsert) { 
      RecursiveClass.doStuffOnInsert(); 
     } 
     if(Trigger.isUpdate) { 
      RecursiveClass.doStuffOnUpdate(); 
     }   
    }  
} 

Classe:

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; 
    } 
} 

Sur la base de cela, je me attends à 100% la couverture de code, mais lorsque vous exécutez la ligne RecursiveClass.doStuffOnUpdate(); dans le déclencheur ne sera pas exécuté car la variable statique semble toujours être définie. D'après ce que j'ai lu dans la documentation, les variables statiques ne sont sauvegardées que pendant une transaction (c'est-à-dire une insertion ou une mise à jour). Est-ce que la mise à jour de la classe de test ne serait pas une toute nouvelle transaction ou est-ce que je la comprends mal?

La seule façon de contourner ce problème est de diviser les variables statiques entre une pour l'insertion et une pour la mise à jour.

Répondre

2

Cela se produit car les deux instructions DML insert et update font partie de la même transaction Apex et l'extrait suivant l'explique bien.

Une variable statique est statique uniquement dans le cadre de la transaction Apex. Ce n'est pas statique à travers le serveur ou l'organisation entière. La valeur d'une variable statique persiste dans le contexte d'une transaction unique et est réinitialisée à travers les limites de la transaction. Par exemple, si une requête Apex DML provoque le déclenchement d'un déclencheur plusieurs fois, les variables statiques persistent sur ces invocations de déclencheur.

Vous pouvez trouver un exemple détaillé à ce sujet here.

Edit:

Une chose, vous devez mettre à jour votre déclencheur pour gérer update ainsi que

trigger RecursiveTrigger on Account(before insert, before update) { 
} 

Edit:

Et, voici comment vous pouvez atteindre 100% de couverture

@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; 
    } 
} 

Espérons que cela aide.

+0

Merci pour la réponse rapide! Existe-t-il un moyen de faire des transactions séparées dans une classe de test?Si nous travaillons avec des méthodes de test qui sont auto-suffisantes (SeeAllData = false), je voudrais insérer des comptes plutôt que d'interroger la base de données et de les mettre à jour. – Twan

+0

Cette mise à jour était dans mon vrai code mais je l'ai oublié dans mon exemple :) Merci pour la réponse! – Twan

+0

RecursiveClass.RunOnce = true; ne s'exécute pas avant que Trigger ne soit en cours d'exécution. While (Trigger.isExecuting) n'est pas nécessaire; –

2

Votre test doit ressembler à

@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; 
} 
} 

Configuration de votre variable statique true avant la prochaine DML vous donne l'idée d'une prochaine action de l'utilisateur. Les variables statiques sont utilisées pour empêcher les boucles de déclenchement. Comme, vous avez mis à jour un objet, puis dans un déclencheur vous avez fait quelques manipulations et ensuite mettre à jour cet objet. Cela peut provoquer une boucle infinie de mise à jour du déclencheur. Pour empêcher ces variables statiques sont utilisés.