Apex テストのテストデータを作成する
学習の目的
この単元を完了すると、次のことができるようになります。
- テストユーティリティクラスを作成する。
- テストユーティリティメソッドを使用してさまざまなテストケースのテストデータを設定する。
- クラスのすべてのテストメソッドを実行する。
Apex テストのテストデータを作成する
テストユーティリティクラスを使用して、テストデータ設定のために再利用可能なメソッドを追加します。
前提条件
前の単元の「Apex トリガーをテストする」の前提条件の操作を完了します (まだ完了していない場合)。
テストユーティリティクラスを追加する
テストデータ作成をユーティリティクラスメソッドへのコールに置き換えて、前のテストメソッドをリファクタリングしましょう。最初に、テストユーティリティクラスを作成する必要があります。
TestDataFactory
クラスは、特殊な種類のクラスです。@isTest
アノテーションが付加された公開クラスで、実行中のテストからのみアクセスできます。テストユーティリティクラスには、テストメソッドからコールしてテストデータの設定などの便利なタスクを実行できるメソッドが含まれます。テストユーティリティクラスは、組織のコードサイズ制限から除外されます。
TestDataFactory
クラスを追加する手順は、次のとおりです。
- 開発者コンソールで、[File (ファイル)] | [New (新規)] | [Apex Class (Apex クラス)] をクリックし、クラス名に
TestDataFactory
と入力し、[OK] をクリックします。 - デフォルトのクラス本文を次のコードで置き換えます。
@isTest public class TestDataFactory { public static List<Account> createAccountsWithOpps(Integer numAccts, Integer numOppsPerAcct) { List<Account> accts = new List<Account>(); for(Integer i=0;i<numAccts;i++) { Account a = new Account(Name='TestAccount' + i); accts.add(a); } insert accts; List<Opportunity> opps = new List<Opportunity>(); for(Integer j=0;j<numAccts;j++) { Account acct = accts[j]; // For each account just inserted, add opportunities for(Integer k=0;k<numOppsPerAcct;k++) { opps.add(new Opportunity(Name=acct.Name + ' Opportunity ' + k, StageName='Prospecting', CloseDate=System.today().addMonths(1), AccountId=acct.Id)); } } // Insert all opportunities for all accounts. insert opps; return accts; } }
このテストユーティリティクラスには 1 つの静的メソッド createAccountsWithOpps()
が含まれます。このメソッドは取引先数 (numAccts
パラメーターに保持) と取引先ごとに作成する関連商談数 (numOppsPerAcct
パラメーターに保持) を受け入れます。メソッドの最初のループでは、指定された数の取引先を作成し、accts
リスト変数に保存します。最初のループの後、insert()
DML ステートメントがコールされて、リスト内のすべての取引先をデータベース内に作成します。
2 つ目のループでは商談を作成します。各商談グループは、1 つの取引先にリンクしているため、外部ループは取引先を反復処理し、その中にネストされたループでは、現在の取引先の関連商談を作成します。次回ネストループが実行されるとき、add()
メソッドを使用して商談が同じリストに追加されます。商談は、AccountId
項目を使用して親取引先にリンクされます。作成されるすべての商談の合計数は、商談数と取引先数の積 (numOppsPerAcct
*numAccts
) になります。次に、insert()
DML ステートメントをループ外で効率的にコールし、すべての取引先についてコレクション内のすべての商談を 1 回のコールのみで作成します。
最後に、このメソッドは新規取引先のリストを返します。
テストデータ作成用のユーティリティメソッドをコールする
テストユーティリティクラスを追加したところで、次はこのクラスを利用するように TestAccountDeletion
テストクラスを変更します。TestDataFactory.createAccountsWithOpps(1,1)
コールから返される配列には 1 つの Account sObject が含まれます。
変更されたテストメソッドは次のようになります。より短いバージョンです。
@isTest private class TestAccountDeletion { @isTest static void TestDeleteAccountWithOneOpportunity() { // Test data setup // Create one account with one opportunity by calling a utility method Account[] accts = TestDataFactory.createAccountsWithOpps(1,1); // Perform test Test.startTest(); Database.DeleteResult result = Database.delete(accts[0], false); Test.stopTest(); // Verify that the deletion should have been stopped by the trigger, // so check that we got back an error. System.assert(!result.isSuccess()); System.assert(result.getErrors().size() > 0); System.assertEquals('Cannot delete account with related opportunities.', result.getErrors()[0].getMessage()); } }
さまざまな条件でテストする
トリガーに対して可能性のあるすべての入力をテストするには、1 つのテストメソッドでは不十分です。商談のない取引先が削除される場合など、他の条件もテストする必要があります。また、1 件のレコードだけでなく、大量のレコードで同じシナリオをテストする必要もあります。3 つのテストメソッドが追加されたテストクラスの更新バージョンを次に示します。この更新バージョンのクラスを保存します。
@isTest private class TestAccountDeletion { @isTest static void TestDeleteAccountWithOneOpportunity() { // Test data setup // Create one account with one opportunity by calling a utility method Account[] accts = TestDataFactory.createAccountsWithOpps(1,1); // Perform test Test.startTest(); Database.DeleteResult result = Database.delete(accts[0], false); Test.stopTest(); // Verify that the deletion should have been stopped by the trigger, // so check that we got back an error. System.assert(!result.isSuccess()); System.assert(result.getErrors().size() > 0); System.assertEquals('Cannot delete account with related opportunities.', result.getErrors()[0].getMessage()); } @isTest static void TestDeleteAccountWithNoOpportunities() { // Test data setup // Create one account with no opportunities by calling a utility method Account[] accts = TestDataFactory.createAccountsWithOpps(1,0); // Perform test Test.startTest(); Database.DeleteResult result = Database.delete(accts[0], false); Test.stopTest(); // Verify that the deletion was successful System.assert(result.isSuccess()); } @isTest static void TestDeleteBulkAccountsWithOneOpportunity() { // Test data setup // Create accounts with one opportunity each by calling a utility method Account[] accts = TestDataFactory.createAccountsWithOpps(200,1); // Perform test Test.startTest(); Database.DeleteResult[] results = Database.delete(accts, false); Test.stopTest(); // Verify for each record. // In this case the deletion should have been stopped by the trigger, // so check that we got back an error. for(Database.DeleteResult dr : results) { System.assert(!dr.isSuccess()); System.assert(dr.getErrors().size() > 0); System.assertEquals('Cannot delete account with related opportunities.', dr.getErrors()[0].getMessage()); } } @isTest static void TestDeleteBulkAccountsWithNoOpportunities() { // Test data setup // Create accounts with no opportunities by calling a utility method Account[] accts = TestDataFactory.createAccountsWithOpps(200,0); // Perform test Test.startTest(); Database.DeleteResult[] results = Database.delete(accts, false); Test.stopTest(); // For each record, verify that the deletion was successful for(Database.DeleteResult dr : results) { System.assert(dr.isSuccess()); } } }
すべてのテストメソッドを実行する
最後のステップでは、テストクラスのテストメソッドを実行します。クラスはより包括的なテストが含み、テストデータファクトリを使用するようにリファクタリングされています。TestAccountDeletion
クラスのテストはすでに実行済みであるため、このテストクラスを再実行して、そのテストメソッドをすべて実行するだけです。
- 同じテストを実行するには、[Tests (テスト)] タブをクリックし、テスト実行を選択して、[Test (テスト)] | [Rerun (再実行)] をクリックします。
- [Tests (テスト)] タブで最新のテスト実行を展開して結果を確認します。テスト実行で 4 つのテストがすべて合格したとレポートされます。
リソース