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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何避免在创建用户的Salesforce测试中出现MIXED_DML_OPERATION错误相关的知识,希望对你有一定的参考价值。

有时在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;
    }

}
答案

我猜这里的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错误停止发生。

另一答案

好像你找到了一个解决方法。我只是想尝试清理为什么你在哪里得到这个错误。

我认为你遇到了这个问题(根据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)说:

在以前的版本中,在涉及触发器的单个事务中,您可以对多种类型的sObject执行DML操作,例如,您可以插入帐户,然后插入用户。从Summer '08开始,您只能从以下sObject列表中对单一类型的sObject执行DML操作。

例如,您无法插入帐户,然后插入用户或更新组,然后插入组成员。

  • GroupMember
  • QueueSObject
  • 用户
  • UserRole的
  • UserTerritory
  • 领土

此外,User和Territory现在支持插入和更新DML操作,UserRole现在支持插入,更新删除和upsert DML操作。

以下sObjects不支持Apex DML操作:

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • UserAccountTeamMember
另一答案

salesforce文档中实际记录了此行为:http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType。阅读它所说的“重要”这个的主要例外是当你在测试中使用runAs方法时

另一答案

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

其他用途的runAs

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

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

希望这可以帮助

Reference

以上是关于如何避免在创建用户的Salesforce测试中出现MIXED_DML_OPERATION错误的主要内容,如果未能解决你的问题,请参考以下文章

测试时如何避免再次创建相同的用户[关闭]

Salesforce 如何把签卡数据同步到中控系统

如何在salesforce中建立opportunity object

我们正在使用 JMeter 测试 Salesforce 应用程序。单个用户从 JMeter 登录需要 35 秒,但是从 UI 可能需要 15 秒

如何在salesforce中设计dashboard

避免将记录插入Salesforce的解决方案