Apex テスト 備忘録

#1.テストメソッドの雛形
```java

@isTest
private class XXXXXXTest {
    @testSetup
    static void setup() {
        // 各テストメソッドで使用できるテストデータを作成する
    }

    @isTest
    static void XXXTest() {
        System.runAs(new User(ID = UserInfo.getUserID())) {
            /* ＝＝＝＝＝＝テストデータ準備＝＝＝＝＝＝ */
            // 各SObjectデータ作成
            // テストデータ：取引先
            Account testDataAccount = TestDataFactory.getTestDataAccount();
            insert testDataAccount;

            /* ＝＝＝＝＝＝テストメソッド起動＝＝＝＝＝＝ */
            Test.startTest();
            // 対象メソッドを呼び出す
            Test.stopTest();

            /* ＝＝＝＝＝＝結果検証＝＝＝＝＝＝ */      
            // 実行結果と期待値の検証
        }
    }
}
```

#2.テストデータの使用範囲及び作成方式
テストデータの使用範囲は下記の種類があります。

- **【テストメソッド内】**
- **【テストメソッド間】**
  - ①@testSetup
  - ②共通メソッド
- **【テストクラス間】**
  - ①テストユーティリティクラス
  - ②Test.loadData メソッド

##【テストメソッド内】作成方式
```java

@isTest
private class MyTestClass {
    @isTest static void myTest() {
        //取引先データ作成
        Account acc = new Account(Name = 'Sample Account');
        insert acc;
    }
}
```
##【テストメソッド間】作成方式
###①@testSetup
```java

@isTest
private class MyTestClass{
    @testSetup
    static void setup() {
        Account acc = new Account(Name = 'Sample Account');
        insert acc;
    }

    @isTest
    static void test1() {
        // @testSetupで作成したレコードをSOQLで取得できる
        Account acc = [SELECT Id, Name FROM Account];
    }
}
```
###②共通メソッド

```java

@isTest
private class MyTestClass {
    static Account acc;
    
    @isTest static void myTest1() {
        //取引先データ作成
        createAccount('myTest01');
        
        // ～～省略～～
    }
    
    @isTest static void myTest2() {
        //取引先データ作成
        createAccount('myTest02');
        
        // ～～省略～～
    }
    
    // 取引先テストデータ作成
    static void createAccount(String acccName) {
        //取引先データ作成
        acc = new Account(Name = acccName);
        insert acc;
    }
}
```

##【テストクラス間】作成方式
###①テストユーティリティクラス

```java:TestDataFactory
/**
 * 各オブジェクトのテストデータ生成Factory
 * 
 */
@isTest
public class TestDataFactory {
    /**
     * テストデータ：取引先
     */
    public static Account getTestDataAccount() {
        // テストデータの作成
        Account testData = new Account();
        testData.Name = 'テストデータ';
        testData.NameKana__c = 'テストデータ';
        return testData;
    }

    /**
     * テストデータ：取引先責任者
     */
    public static Contact getTestDataContact() {
        // テストデータの作成
        Contact testData = new Contact();
        testData.FirstName = 'firstName';
        testData.LastName = 'lastName';
        testData.Phone='08012345678';
        testData.Email = 'xuwenzhen@gmail.com';
        return testData;
    }
}
```
もっと汎用化したい場合、[Apexテストデータ作成の汎用化](https://qiita.com/xuwenzhen/items/b810e7ed1f62a2c6dc31)をご参照ください。
###②Test.loadData メソッド
```java

@isTest 
private class DataUtil {
    static testmethod void testLoadData() {
        List<sObject> ls = Test.loadData(Account.sObjectType, 'testAccounts');
        Account a1 = (Account)ls[0];
        String acctName = a1.Name;

        // ～～省略～～
    }
}
```
#3.その他
###System.runAs
- レコードの共有権限でSOQLを実行する(MetaData権限無視)
- テストクラスに[混合 DML 操作](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dml_non_mix_sobjects_test_methods.htm)許可
- 指定パッケージバージョンの Apex クラスまたはトリガを実行する

###Test.startTest / Test.stopTest
- startとstopの間だけでガバナ制限がカウントされ、データ準備のためのコード実行分がカウントされない。
- 非同期処理は同期として実行する

###System.assertEquals / System.assert
- System.assertEquals(期待値, 実際の値)
- System.assert(評価の式)

###Test.isRunningTest
テストクラスで実行されたかの判定

###Test.getStandardPricebookId
組織内の標準価格表の ID を取得する

###@TestVisible
Privateまたはprotectedメンバーはテストクラスへ公開する

###テストデータパターン
- ポジティブな動作に対するテスト
- ネガティブな動作に対するテスト
- 単一レコードのテスト
- 複数レコードのテスト（トリガの場合、201件）

###注意事項
- IDをハードコーディングしない
- できるだけ「DescribeSObjectResult.getRecordTypeInfosByDeveloperName」でレコードタイプを取得する
- できるだけ「@IsTest(SeeAllData=true)」を使わないようにする
- カスタム設定の代わりにカスタムデータデータ型を検討する
- バッチ処理の対象データはBatch Sizeを超えないように考慮する必要があります。

#4.Apex テスト例（※随時更新）
 - [HttpCalloutMock と StubProvider のお試し](https://qiita.com/xuwenzhen/items/bc76b99562225eed8b65) 
 - [テストクラスにApex電子メール送信の検証方法](https://qiita.com/xuwenzhen/items/696f0183323bb061de38)

#5.ダミーコードでリリース優先一時対応案
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/51dcf71b-ee7b-d650-b089-d064579018a8.png)

```java

/**
 * ダミークラス
 * 
 */
public class DummyClass {
    public static void dummyMethod() {
        Integer i = 0;
        i = 0;
        i = 0;
        i = 0;
          ・
          ・
         // 10000行とか
    }
}
```
```java

/**
 * ダミークラスのテストクラス
 * 
 */
@isTest
private class DummyClassTest {
    @isTest
    static void dummyMethodTest() {
        DummyClass.dummyMethod();
    }
}
```