如何避免在创建用户的Salesforce测试中出现MIXED_DML_OPERATION错误

时间:2010-03-05 14:39:46

标签: unit-testing salesforce apex-code

有时在Salesforce测试中,您需要创建User对象以作为特定类型的用户运行部分测试。

但是,自Salesforce Summer 08更新以来,尝试在同一测试中创建用户对象和普通对象(如帐户)会导致以下错误:

  

MIXED_DML_OPERATION,更新非安装对象后,不允许对安装对象进行DML操作(反之亦然):用户,原始对象:帐户

请注意,从Eclipse / Force.com IDE运行测试时不会发生错误,但是当您部署到Salesforce然后从Salesforce中运行测试时,确实会发生错误。

如何重新编写测试以避免此错误?

以下是导致错误的测试的简单示例:

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='standarduser@testorg.com', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='standarduser@testorg.com');
    Account a = new Account(Firstname='Terry', Lastname='Testperson');
    insert a;

    System.runAs(u) {
        a.PersonEmail = 'test@madeupaddress.com';
        update a;
    }

}

5 个答案:

答案 0 :(得分:40)

我猜这里的Salesforce人员不多。

我找到了一个解决方案,我不知道它为什么会起作用,但它确实有效。

访问普通对象的测试的所有部分都需要包装在显式使用当前用户的System.runAs中,如下所示:

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

因此,问题中给出的示例text_mixed_dmlbug方法将变为:

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='standarduser@testorg.com', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='standarduser@testorg.com');
        a = new Account(Firstname='Terry', Lastname='Testperson');
        insert a;
    }
    System.runAs(u) {
        a.PersonEmail = 'test@madeupaddress.com';
        update a;
    }

}

然后MIXED_DML_OPERATION错误停止发生。

答案 1 :(得分:13)

好像你找到了一个解决方法。我只想尝试清除你为什么会出现这个错误。

我认为你遇到了这个问题(按http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm):

  

在DML操作中无法一起使用的sObjects

     

某些sObject要求您对每个事务仅对一种类型执行DML操作。例如,您无法插入帐户,然后在单个事务中插入用户或组成员。以下sObjects不能在事务中一起使用:

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

重要的主要例外   这是在你使用runAs的时候   测试中的方法。

此外,Summer 08 Release notes(该链接是PDF)说:

  

在以前的版本中,单个版本   涉及触发器的事务,   你可以执行DML操作   用于多种类型的sObject   例如,您可以插入一个帐户,   然后插入一个用户。截至夏季   '08,你只能执行DML   对单一类型的sObject的操作   来自以下sObjects列表。

     

例如,您无法插入   帐户,然后插入用户或更新   一个组,然后插入一个组   构件。

     
      
  •   
  • GroupMember
  •   
  • QueueSObject
  •   
  • 用户
  •   
  • 的UserRole
  •   
  • UserTerritory
  •   
  • 地区
  •   
     

此外,现在还有用户和区域   支持插入和更新DML   操作和UserRole   现在支持插入,更新删除   并upsert DML操作。

     

不支持Apex DML操作   在以下sObjects:

     
      
  • AccountTerritoryAssignmentRule
  •   
  • AccountTerritoryAssignmentRuleItem
  •   
  • UserAccountTeamMember
  •   

答案 2 :(得分:7)

此行为实际记录在salesforce文档中:http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType。阅读它所说的“重要 对此的主要例外是在测试“

中使用runAs方法时

答案 3 :(得分:1)

刚刚在文档中找到了这个:

  

runAs

的其他用途      

您还可以使用runAs方法在测试中执行混合DML操作,方法是在runAs块中包含DML操作。通过这种方式,您可以绕过在与其他sObjects一起插入或更新设置对象时返回的混合DML错误。请参阅在DML操作中无法一起使用的sObjects

所以看起来RunAs解决方法不是一种解决方法,但Salesforce认为它是解决混合DML问题的唯一方法。

希望这有帮助

Reference

答案 4 :(得分:0)

在顶点的单个事务中尝试创建用户和其他对象记录时,此错误非常常见。

顶点类/触发中的解决方法:遇到错误时,使用将来的方法创建用户

测试类中的解决方法:请勿尝试创建新的用户数据,而应使用))>

代码段位于- https://thesalesforcedev.blogspot.com/2019/07/mixeddmloperation-dml-operation-on.html