Memos About Salesforce

Salesforceにハマってたこと!

SFDC コールアウトのテスト

実は ApexクラスでHTTP Calloutsの処理をするクラスに対して

普通にテストクラスを作って

実行すると次のようなエラーが発生して処理がスキップされてしまいます。

f:id:jude2016:20180919142756p:plain

HTTP Calloutsのテストクラスを作成するには"HttpCalloutMock"を実装した

クラスが必要です。

これを用意しテストクラス内で

次のような宣言で呼び出すことで擬似的な

HTTP Calloutsの結果を取得することができるとのことです。

Test.setMock(HttpCalloutMock.class, new YourImplementsHttpCalloutMockClass());

今回、郵便番号検索機能を例にしたテストクラスを

共有したいと思います

目次

ZipCloudのhttp calloutsのテスト

zipCloudのクラス例をテストするにはまず

sfdc側が用意した「HttpCalloutMock」を実装したMockクラスを作成する必要がある

zipCloudのクラス例
public with sharing class SearchByZipCode{
    /**
     * get JSON Data From Google Api By PostalCode
     * 郵便番号でグーグルAPIから住所データを取得
     * @param  String postalCD 郵便番号
     * @return JSON Data 取得したJson
     */
    public static String getJSONByPostCD(String zipcode){
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        List<String> zipcodeFormat = new String[]{zipcode};
        String url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';
        req.setHeader('Content-Type', 'application/json');
        req.setHeader('Accept','application/json');
        req.setEndpoint(url);
        req.setMethod('GET');
        req.setTimeout(20000);
        Boolean isError = false;
        try{
            res = http.send(req);
        }catch(System.CalloutException ce){
            isError = true;
            return ce.getMessage();
        }
        return res.getBody();
    }
}
「HttpCalloutMock」を実装したMockクラス例

1データ、個人的にあまり好きではないため、2データ用意した(笑)

@isTest
public class ZipCloudCalloutMock implements HttpCalloutMock {
    // エラー発生フラグ
    public Boolean errorFlg { get; set; }
    /**
   * @description コンストラクタ
   * @param errFlg エラー発生フラグ
   *
   */
    public ZipCloudCalloutMock(Boolean errFlg) {
        this.errorFlg = errFlg;
    }

    public HTTPResponse respond(HTTPRequest request) {
        // エラーフラグがtrueだった場合は通信エラーを投げる
        if (this.errorFlg) {
            throw new System.CalloutException('通信エラー');
        }
        // create fake data map
        Map<String, Object> responseMap = createFakeData();

        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody(JSON.serialize(responseMap));
        response.setStatusCode(200);
        return response;
    }

    // create fake data map
    private Map<String, Object> createFakeData(){
        // fake data list
        List<Object> addDataList = new List<Object>();
        // fake data map
        Map<String, Object> responseMap = new Map<String, Object>();
        // fake data 1
        Map<String, String> addData1Map = new Map<String, String>();
        addData1Map.put('address1', '愛知県');
        addData1Map.put('address2', '清須市');
        addData1Map.put('address3', '春日県');
        addData1Map.put('kana1', 'アイチケン');
        addData1Map.put('kana2', 'キヨスシ');
        addData1Map.put('kana3', 'ハルヒアガタ');
        addData1Map.put('prefcode', '23');
        addData1Map.put('zipcode', '4520962');
        // Store data1 into data list
        addDataList.add(addData1Map);
        // fake data 1
        Map<String, String> addData2Map = new Map<String, String>();
        addData2Map.put('address1', '愛知県');
        addData2Map.put('address2', '清須市');
        addData2Map.put('address3', '春日江先');
        addData2Map.put('kana1', 'アイチケン');
        addData2Map.put('kana2', 'キヨスシ');
        addData2Map.put('kana3', 'ハルヒエサキ');
        addData2Map.put('prefcode', '23');
        addData2Map.put('zipcode', '4520962');
        // Store data2 into data list
        addDataList.add(addData2Map);

        responseMap.put('message', null);
        responseMap.put('results', addDataList);// data list put in data map
        responseMap.put('status', 200);
        return responseMap;
    }
}
Http Calloutsのテスト

上記で作成したMockクラス:ZipCloudCalloutMockを用いてテストクラスを作成

@IsTest
private class SearchByZipCodeTest{
    static testMethod void search_Normal_Test() {
        String testZipcode = '4520962';
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new ZipCloudCalloutMock(false));
        String result = SearchByZipCode.getJSONByPostCD(testZipcode);
        System.debug('call out result-ok:' + result);
        Test.stopTest();
    }

    static testMethod void search_Abnormal_Test() {
        String testZipcode = '4520962';
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new ZipCloudCalloutMock(true));
        String result = SearchByZipCode.getJSONByPostCD(testZipcode);
        System.debug('call out result-no:' + result);
        Test.stopTest();
    }
}

まとめ

Webserviceを使ったクラスのテストを実装するには

手順が下記通り

1:「HttpCalloutMock」を実装したカスタムのMockクラスを作成し、疑似テストデータを用意する

2:「Http」をコールしたクラスのテストクラスを作成し、中に

 「1」で用意したカスタムMockクラスを下記のようにコールする

 Test.setMock(HttpCalloutMock.class, new カスタムMockクラス(引数がある場合設定));

静的リソースを使用したテストもある、次回、共有します。