web-dev-qa-db-fra.com

Comment éviter l'erreur MIXED_DML_OPERATION dans les tests Salesforce qui créent des utilisateurs

Parfois, dans les tests Salesforce, vous devez créer des objets Utilisateur pour exécuter une partie du test en tant que type d'utilisateur spécifique.

Cependant, depuis la mise à jour de Salesforce Summer 08, les tentatives de création à la fois d'objets utilisateur et d'objets normaux (tels que des comptes) dans le même test entraînent l'erreur suivante:

MIXED_DML_OPERATION, l'opération DML sur un objet de configuration n'est pas autorisée après avoir mis à jour un objet non configuré (ou vice versa): utilisateur, objet d'origine: compte

Notez que l'erreur ne se produit pas lorsque vous exécutez les tests à partir de l'IDE Eclipse/Force.com, mais elle se produit lorsque vous déployez sur Salesforce, puis exécutez les tests à partir de Salesforce.

Comment réécrire mes tests pour éviter cette erreur?

Voici un exemple simple d'un test qui provoque l'erreur:

static testMethod void test_mixed_dmlbug() {        
    Profile p = [select id from profile where name='(some profile)'];
    UserRole r = [Select id from userrole where name='(some role)'];
    User u = new User(alias = 'standt', email='[email protected]', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='[email protected]');
    Account a = new Account(Firstname='Terry', Lastname='Testperson');
    insert a;

    System.runAs(u) {
        a.PersonEmail = '[email protected]';
        update a;
    }

}
32
codeulike

Je pense que peu de gens Salesforce ici.

J'ai trouvé une solution, je ne sais pas pourquoi ça marche, mais ça marche.

Toutes les parties du test qui accèdent aux objets normaux doivent être encapsulées dans un System.runAs qui utilise explicitement l'utilisateur actuel, comme ceci:

User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
System.runAs ( thisUser ) {
    // put test setup code in here
}

Ainsi, l'exemple de méthode text_mixed_dmlbug donné dans la question, deviendrait:

static testMethod void test_mixed_dmlbug() {  
    User u;
    Account a;      
    User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
    System.runAs ( thisUser ) {
        Profile p = [select id from profile where name='(some profile)'];
        UserRole r = [Select id from userrole where name='(some role)'];
        u = new User(alias = 'standt', email='[email protected]', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='[email protected]');
        a = new Account(Firstname='Terry', Lastname='Testperson');
        insert a;
    }
    System.runAs(u) {
        a.PersonEmail = '[email protected]';
        update a;
    }

}

Ensuite, les erreurs MIXED_DML_OPERATION cessent de se produire.

40
codeulike

Il semble que vous ayez trouvé une solution de contournement. Je voulais juste essayer de comprendre pourquoi vous obteniez cette erreur.

Je pense que vous rencontrez ce problème (par http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm ):

sObjets qui ne peuvent pas être utilisés ensemble dans les opérations DML

Certains sObjects nécessitent que vous effectuiez des opérations DML sur un seul type par transaction. Par exemple, vous ne pouvez pas insérer un compte, puis insérer un utilisateur ou un membre du groupe dans une seule transaction. Les sObjects suivants ne peuvent pas être utilisés ensemble dans une transaction:

* Group1
* GroupMember
* QueueSObject
* User2
* UserRole
* UserTerritory
* Territory

Important La principale exception à cela est lorsque vous utilisez la méthode runAs dans un test.

De plus, les Notes de version Summer 08 (ce lien est un PDF) disent:

Dans les versions précédentes, dans une seule transaction impliquant des déclencheurs, vous pouviez effectuer des opérations DML sur plusieurs types de sObject, par exemple, vous pouviez insérer un compte, puis insérer un utilisateur. Depuis Summer '08, vous ne pouvez effectuer des opérations DML que sur un seul type de sObject à partir de la liste suivante de sObjects.

Par exemple, vous ne pouvez pas insérer un compte, puis insérer un utilisateur ou mettre à jour un groupe, puis insérer un membre du groupe.

  • Groupe
  • Membre du groupe
  • QueueSObject
  • Utilisateur
  • Rôle d'utilisateur
  • UserTerritory
  • Territoire

De plus, l'utilisateur et le territoire prennent désormais en charge les opérations DML d'insertion et de mise à jour, et UserRole prend désormais en charge les opérations DML d'insertion, de mise à jour, de suppression et de mise à jour.

Les opérations Apex DML ne sont pas prises en charge sur les sObjects suivants:

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • UserAccountTeamMember
13
Paddyslacker

Ce comportement est en fait documenté dans la documentation Salesforce: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType . Lisez où il est dit "Important La principale exception à cela est lorsque vous utilisez la méthode runAs dans un test"

7
Jorge

Je viens de trouver cela dans la documentation:

Autres utilisations de runAs

Vous pouvez également utiliser la méthode runAs pour effectuer des opérations DML mixtes dans votre test en enfermant les opérations DML dans le bloc runAs. De cette façon, vous contournez l'erreur DML mixte qui est retournée par ailleurs lors de l'insertion ou de la mise à jour des objets de configuration avec d'autres sObjects. Voir sObjects qui ne peut pas être utilisé ensemble dans les opérations DML.

Il semble donc que la solution de contournement RunAs ne soit pas une solution de contournement, mais est supposée par Salesforce comme la seule façon de résoudre le problème DML mixte.

J'espère que cela t'aides

Référence

1
fredbe

Cette erreur est si courante lorsque vous tentez de créer des enregistrements d'utilisateurs et d'autres objets dans une seule transaction dans Apex.

Solution de contournement dans la classe/déclencheur apex: utilisez la méthode future pour créer l'utilisateur lorsque l'erreur est rencontrée

Solution de contournement dans la classe de test: n'essayez pas de créer de nouvelles données utilisateur, utilisez plutôt))>

extrait de code sur - https://thesalesforcedev.blogspot.com/2019/07/mixeddmloperation-dml-operation-on.html

0
Hoda Danish