この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

テストメソッドでの混合 DML 操作

テストメソッドでは、DML 操作を実行するコードが System.runAs メソッドブロックで囲まれている場合、DML 操作で同時に使用できない sObjectに記載された sObject とその他の sObject の間の混合 DML 操作の実行が許可されます。たとえば、これによりロールとその他の sObject を持つユーザを同じテスト内で作成できます。

例: System.runAs ブロックでの混合 DML 操作

この例では、混合 DML 操作を System.runAs ブロックで囲み、混合 DML エラーを回避する方法を示します。System.runAs ブロックは、現在のユーザのコンテキストで実行されます。このブロックは、ロールを持つテストユーザとテスト取引先を作成するという混合 DML 操作を実行します。
1@isTest
2private class MixedDML {
3    static testMethod void mixedDMLExample() {  
4        User u;
5        Account a;
6        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
7       // Insert account as current user
8        System.runAs (thisUser) {
9            Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
10            UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
11            u = new User(alias = 'jsmith', email='jsmith@acme.com', 
12                emailencodingkey='UTF-8', lastname='Smith', 
13                languagelocalekey='en_US', 
14                localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
15                timezonesidkey='America/Los_Angeles', 
16                username='jsmith@acme.com');
17            insert u;
18            a = new Account(name='Acme');
19            insert a;
20        }
21    }
22}

テストメソッドで Test.startTestTest.stopTest を使用して混合 DML エラーを回避する

混合 DML 操作を実行するコードブロックを System.runAs ブロックで囲んでも、混合 DML 例外エラーが返されることがあります。これは、テストメソッドが、グループの削除など、他の操作とは混合できない DML 操作を実行する future メソッドをコールした場合に発生する可能性があります。この場合、混合 DML 例外が返されたら、future メソッドコールを行うコードブロックを、Test.stopTest および Test.startTest ステートメントで囲みます。

この例では、Test.startTest および Test.stopTest ステートメントで delete ステートメントを囲むことにより、テストで混合 DML 例外エラーを回避す��方法を示します。delete ステートメントにより、混合 DML 操作は future メソッドで実行されることになるため、ステートメントを Test.startTest および Test.stopTest ステートメントで囲みます。delete ステートメントはトリガを起動し、Util クラスの deleteGroup future メソッドをコールして取引先挿入トリガですでに挿入されていたグループを削除します。

これは、混合 DML 操作を起動するテストクラスです。取引先挿入および削除がトリガを起動します。

1@isTest
2private class RunasTest {
3    static testMethod void mixeddmltest() {
4        // Create the account and group. 
5        Account ac = new Account(Name='TEST ACCOUNT');
6        // Group is created in the insert trigger.
7        insert ac;
8        // Set up user
9        User u1 = [SELECT Id FROM User WHERE UserName='testadmin@acme.com'];
10        System.RunAs(u1){
11            // Add startTest and stopTest to avoid mixed DML error
12            Test.startTest();
13            // Delete the account. 
14            // Group is deleted through future method call in trigger.
15            delete ac;
16            Test.stopTest();
17        }
18    }
19}

これは、グループを挿入する取引先挿入トリガです。

1trigger Account_After_Insert_Trg on Account (after insert) {
2    Group gr = new Group(Name='Test',Type='Regular');
3    insert gr;
4}

これは、future メソッドをコールしてグループを削除する取引先削除トリガです。

1trigger Account_Before_Delete_Trg on Account (before delete) {
2    Util.deleteGroup('Test');
3}

これは、グループを削除する future メソッドです。

1public with sharing class Util {
2    @future
3    public static void deleteGroup(String grNameSet) {
4        List<Group> grList = 
5            [select Id, Name from Group where Name = :grNameSet];
6        delete grList[0];
7    }
8}