💡背景
SalesforceでFlowやトリガーなどでUserオブジェクトを更新するケースでは、裏でAccountやContactなどの**「設定オブジェクト」**も一緒に更新されることがあり、テストクラスでのエラーを引き起こすことがあります。
🔧 発生するエラー
① FIELD_INTEGRITY_EXCEPTION
System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, only portal users can be associated to a contact.
→ これは**ポータルユーザー(Communityユーザー)**を作成 or 更新しようとした際に、Contact
との関連付けが正しくない場合に発生します。
② MIXED_DML_OPERATION
DmlException: Mixed DML operation between setup and non-setup objects
→ これは User
(設定オブジェクト)と、Account
やContact
(非設定オブジェクト)を 同じトランザクション内でDML操作しようとした場合に出る エラーです。
💥 これらのエラーが起こる背景
- Flowやトリガーで
User
を更新する - そのUserがポータルユーザー(=Contactと紐づく必要あり)
- テストクラスで
User
とAccount
/Contact
を同時にInsert/Update - →
FIELD_INTEGRITY_EXCEPTION
orMIXED_DML_OPERATION
が発生
✅ 解決策
🔹テストクラスでのトランザクションを分ける(@TestSetup
を使う)
Salesforceでは User
を他のオブジェクトと同時に操作するのを避けるため、以下のように トランザクションを分ける ことで MIXED_DML_OPERATION
を回避できます。
🧪 テストクラス例
@isTest
private class UserFlowTest {
@TestSetup
static void setup() {
// 取引先・責任者を事前に作成
Account acc = new Account(Name = 'Test');
insert acc;
Contact con = new Contact(LastName = 'Test Contact', AccountId = acc.Id);
insert con;
contactId = con.Id;
}
@isTest
static void testFlow() {
// プロファイルを取得したり、取引先責任者を取得したり
Test.startTest();
// User作成(@TestSetupとは別トランザクションで処理)
User u = new User(
Username = 'testuser@example.com.test',
LastName = 'User',
Email = 'testuser@example.com',
Alias = 'tuser',
TimeZoneSidKey = 'Asia/Tokyo',
LocaleSidKey = 'ja_JP',
EmailEncodingKey = 'UTF-8',
LanguageLocaleKey = 'ja',
ProfileId = profileId,
ContactId = contactId,
CommunityNickname = 'testuser'
);
insert u;
// insert後にフローが動いてもトランザクション内ではユーザーのみのためMIXED_DML_OPERATIONない
System.runAs(u) {
Test.startTest();
try {
// テストしたい処理
} catch (Exception e) {
System.debug('テスト実行中に例外が発生: ' + e.getMessage());
}
Test.stopTest();
}
}
}
📌補足
課題 | 解決方法 |
---|---|
FIELD_INTEGRITY_EXCEPTION |
Contactの事前作成+正しいプロファイル設定 |
MIXED_DML_OPERATION |
User を @TestSetup 内で insert することで分離 |
✅ まとめ
-
User
のInsert/Updateには注意が必要(特にCommunityユーザー) -
Account
やContact
との整合性と、DMLの順序・分離がポイント - テストクラスでは
@testSetup
で非設定オブジェクトだけ作成 -
User
の操作は必ず テストメソッド内で行い、DMLの分離を意識する