33

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

但是,自从 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;
    }

}
4

5 回答 5

42

我猜这里还没有多少 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 错误停止发生。

于 2010-03-09T16:47:01.380 回答
13

看来您已经找到了解决方法。我只是想尝试弄清楚为什么您会收到此错误。

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

在 DML 操作中不能一起使用的对象

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

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

重要 主要例外是当您在测试中使用 runAs 方法时。

此外,Summer 08 发行说明(该链接是 PDF)说:

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

例如,您不能先插入一个帐户,然后再插入一个用户,或者更新一个组,然后再插入一个组成员。

  • 团体
  • 团体会员
  • 队列对象
  • 用户
  • 用户角色
  • 用户区域
  • 领土

此外,User 和 Territory 现在支持 insert 和 update DML 操作,UserRole 现在支持 insert、update delete 和 upsert DML 操作。

以下 sObject 不支持 Apex DML 操作:

  • 帐户区域分配规则
  • AccountTerritoryAssignmentRuleItem
  • 用户帐户团队成员
于 2010-03-10T01:16:45.343 回答
7

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

于 2011-07-05T21:44:57.090 回答
1

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

其他用途runAs

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

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

希望这可以帮助

参考

于 2018-03-05T13:54:01.407 回答
0

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

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

测试类中的解决方法:不要尝试创建新的用户数据,而是使用 ))>

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

于 2019-07-25T15:11:58.450 回答