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

发布于 2024-08-24 04:36:01 字数 1498 浏览 9 评论 0原文

有时,在 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='[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;
    }

}

Sometimes in Salesforce tests you need to create User objects to run part of the test as a speciifc type of user.

However since the Salesforce Summer 08 update, attempts to create both User objects and normal objects (such as Accounts) in the same test lead to the following error:

MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object: Account

Note that the error doesn't happen when you run the tests from Eclipse/Force.com IDE, but it does happen when you deploy to Salesforce and then run the tests from within Salesforce.

How do I re-write my tests to avoid this error?

Here's a simple example of a test that causes the error:

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心作怪 2024-08-31 04:36:01

我猜这里还没有多少 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='[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;
    }

}

然后 MIXED_DML_OPERATION 错误停止发生。

Not many Salesforce people on here yet, I guess.

I found a solution, I don't know why it works, but it works.

All parts of the test that access normal objects need to be wrapped in a System.runAs that explicitly uses the current user, like this:

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

So, the example text_mixed_dmlbug method given in the question, would become:

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

}

Then the MIXED_DML_OPERATION errors stop happening.

去了角落 2024-08-31 04:36:01

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

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

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

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

<前><代码>* 组 1
* 团体成员
* 队列对象
* 用户2
* 用户角色
* 用户区域
* 领土

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

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

在以前的版本中,在单个
涉及触发器的交易,
您可以执行 DML 操作
不止一种类型的 sObject,对于
例如,您可以插入一个帐户,
然后插入一个用户。从夏季开始
'08,只能执行DML
对单一类型 sObject 的操作
来自以下 sObject 列表。

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

  • 群组成员
  • 队列对象
  • 用户
  • 用户角色
  • 用户区域
  • 领土

此外,现在的用户和区域
支持插入和更新DML
操作和用户角色
现在支持插入、更新删除
并更新插入 DML 操作。

不支持 Apex DML 操作
在以下 sObject 上:

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • 用户帐户团队成员

It seems like you've found a workaround. I just wanted to try and clear up why you where getting this error.

I think you are running into this issue (per http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm):

sObjects That Cannot Be Used Together in DML Operations

Some sObjects require that you perform DML operations on only one type per transaction. For example, you cannot insert an account, then insert a user or a group member in a single transaction. The following sObjects cannot be used together in a transaction:

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

Important The primary exception to
this is when you are using the runAs
method in a test.

In addition, the Summer 08 Release notes (that link is a PDF) say:

In previous releases, in a single
transaction that involved triggers,
you could perform DML operations on
more than one type of sObject, for
example, you could insert an account,
then insert a user. As of Summer
'08, you can only perform DML
operations on a single type of sObject
from the following list of sObjects.

For example, you cannot insert an
account, then insert a user, or update
a group, then insert a group
member.

  • Group
  • GroupMember
  • QueueSObject
  • User
  • UserRole
  • UserTerritory
  • Territory

In addition, User and Territory now
support the insert and update DML
operations, and UserRole
now supports the insert, update delete
and upsert DML operations.

Apex DML operations are not supported
on the following sObjects:

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • UserAccountTeamMember
猫卆 2024-08-31 04:36:01

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

This behavior is actually documented in the salesforce documentation: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType. Read where it say "Important
The primary exception to this is when you are using the runAs method in a test"

顾北清歌寒 2024-08-31 04:36:01

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

runAs的其他用途

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

因此,RunAs 解决方法似乎不是解决方法,但 Salesforce 认为它是解决混合 DML 问题的唯一方法。

希望这有帮助

参考

Just found this in the documentation:

Other Uses of runAs

You can also use the runAs method to perform mixed DML operations in your test by enclosing the DML operations within the runAs block. In this way, you bypass the mixed DML error that is otherwise returned when inserting or updating setup objects together with other sObjects. See sObjects That Cannot Be Used Together in DML Operations.

So it looks like the RunAs workaround is not a workaround but is assumed by Salesforce as the only way of going by the mixed DML issue.

Hope this helps

Reference

好听的两个字的网名 2024-08-31 04:36:01

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

apex 类/触发器中的解决方法:遇到错误时使用 future 方法创建用户

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

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

This error is so common when attempting to create user and other objects records in a single transaction in apex.

Workaround in apex class/trigger : use future method for creating user when encountered the error

Workaround in test class : don't try creating a new user data, instead use ))>

code-snippet at -
https://thesalesforcedev.blogspot.com/2019/07/mixeddmloperation-dml-operation-on.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文