ユーザーを作成するSalesforceテストでMIXED_DML_OPERATIONエラーを回避する方法
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;
}
}
ここにはまだ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操作で一緒に使用できないsObject
一部のsObjectでは、トランザクションごとに1つのタイプのみでDML操作を実行する必要があります。たとえば、アカウントを挿入してから、ユーザーまたはグループメンバーを1つのトランザクションに挿入することはできません。次のsObjectをトランザクションで一緒に使用することはできません。
* Group1 * GroupMember * QueueSObject * User2 * UserRole * UserTerritory * Territory
重要これに対する主な例外は、テストでrunAsメソッドを使用している場合です。
さらに、 Summer 08 Release notes (そのリンクはPDFです)は次のように言っています
以前のリリースでは、トリガーを含む単一のトランザクションで、複数のタイプのsObjectに対してDML操作を実行できました。たとえば、アカウントを挿入してからユーザーを挿入できました。 Summer '08以降、次のsObjectのリストから、単一タイプのsObjectに対してのみDML操作を実行できます。
たとえば、アカウントを挿入してからユーザーを挿入したり、グループを更新してからグループメンバーを挿入したりすることはできません。
- グループ
- グループメンバー
- QueueSObject
- ユーザー
- UserRole
- UserTerritory
- 地域
さらに、UserおよびTerritoryは、DMLの挿入および更新操作をサポートし、UserRoleは、DMLの挿入、更新、削除および更新/挿入操作をサポートするようになりました。
Apex DML操作は、次のsObjectではサポートされていません。
- 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
の回避策は回避策ではないようですが、混合DMLの問題に対処する唯一の方法としてSalesforceが想定しています。
お役に立てれば
このエラーは、apexの単一のトランザクションでユーザーおよびその他のオブジェクトレコードを作成しようとするときによく発生します。
Apexクラス/トリガーの回避策:エラーが発生したときにユーザーを作成するためにfutureメソッドを使用します
テストクラスでの回避策:新しいユーザーデータを作成せず、代わりに))>を使用してください。
- https://thesalesforcedev.blogspot.com/2019/07/mixeddmloperation-dml-operation-on.html のコードスニペット