1回で複数の呼び出しのあるMockテストクラス

HttpCalloutMock インターフェースを実装したクラスを作る

  • 実装クラスはglobalpublic
  • クラスには@isTestをつけよう

サンプルコード)


@isTest global class YourHttpCalloutMockImpl implements HttpCalloutMock {

 global HTTPResponse respond(HTTPRequest req) { 

        } 

}

疑似レスポンスを返すメソッド(respond)を実装する

サンプルコード)

@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock {

    global HTTPResponse respond(HTTPRequest req) {
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"example":"test"}');//複数の呼び出し場合、この部分に複数返却結果を設定する。

//この方法は呼び出し先は区別できません。
        res.setStatusCode(200);
        return res;
    }
}

 

テストコードでTest.setMock()を使いレスポンスを設定

テストコード実行前に以下を書きます。
Test.setMock(HttpCalloutMock.class, new HttpCalloutMockインターフェースの実装クラス());

サンプルコード)

 

@isTest
private class CalloutClassTest {
     @isTest static void testCallout() {
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

        HttpResponse res = CalloutClass.getInfoFromExternalService();
        
        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');

        String actualValue = res.getBody();
        String expectedValue = '{"example":"test"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());
    }
}

 

その他

  • 静的リソースを使って疑似レスポンスを設定する方法もある
  • コールアウトの前にDMLを発行したい場合は、コールアウト部分をTest.startTest()とTest.stopTest()で囲う
    サンプルコード)

@isTest
private class CalloutClassTest {
     @isTest static void testCallout() {
        Account testAcct = new Account('Test Account');
        insert testAcct;

        Test.startTest();

        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());
        
        HttpResponse res = CalloutClass.getInfoFromExternalService();

        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');

        String actualValue = res.getBody();
        String expectedValue = '{"example":"test"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());

        Test.stopTest();
    }
}

 

 

以上の参照先

qiita.com

Testing multiple HTTP callouts

呼び出し先区別のため、下記内容を参照する。

Testing Apex Callouts using HttpCalloutMock | Salesforce Developers Blog

抜粋:

サンプルソース

 

public class ProcessAccountsContacts {
    public static String getJSON(String url) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint(url);
        req.setMethod('GET');
        Http h = new Http();
        HttpResponse res = h.send(req);
        return res.getBody();
    }

    public static Integer processAccountsContacts() {
        String jsonData = getJSON('http://api.example.com/accounts');
        List accounts =
            (List)JSON.deserialize(jsonData, List.class);

        jsonData = getJSON('http://api.example.com/contacts');
        List contacts =
            (List)JSON.deserialize(jsonData, List.class);

        // 'Processing'
        Integer result = accounts.size() + contacts.size();
        return result;
    }
}

上記のソースで我々は二つCALLOUTを作成した、呼び出し先区別のため、下記クラスを作成する。


public class MultiRequestMock implements HttpCalloutMock {
    Map<String, HttpCalloutMock> requests;

    public MultiRequestMock(Map<String, HttpCalloutMock> requests) {
        this.requests = requests;
    }

    public HTTPResponse respond(HTTPRequest req) {

//↓↓↓↓↓↓↓↓↓↓↓↓↓↓呼び出し先の取得↓↓↓↓↓
    HttpCalloutMock mock = requests.get(req.getEndpoint());
        if (mock != null) {
            return mock.respond(req);
            } else {
             throw new MyCustomException('HTTP callout not supported for test methods');
        }
    }

    public void addRequestMock(String url, HttpCalloutMock mock) {
        requests.put(url, mock);
    }
}

テストクラスについて、下記を参照してください。

@isTest
public class MultipleCalloutsTest{
    public static testmethod void testAcctsAndContactsCallout() {
        SingleRequestMock fakeAccountResp = new SingleRequestMock(200,
                                                         'Complete',
                                                         '[{"Name": "sForceTest1"}]',
                                                         null);

        SingleRequestMock fakeContactsResp = new SingleRequestMock(200,
                                                  'Complete',
                                                  '[{"LastName": "Test Last Name"}]',
                                                   null);

        Map<String, HttpCalloutMock> endpoint2TestResp =
                                   new Map<String,HttpCalloutMock>();

//↓↓↓↓↓↓↓↓↓↓↓↓↓↓呼び出し先の設定↓↓↓↓↓
        endpoint2TestResp.put('http://api.example.com/accounts',fakeAccountResp);
        endpoint2TestResp.put('http://api.example.com/contacts',fakeContactsResp);

//↑↑↑↑↑↑↑↑↑↑↑↑↑↑呼び出し先の設定↑↑↑↑↑↑↑

        HttpCalloutMock multiCalloutMock =
                                   new MultiRequestMock(endpoint2TestResp);

        Test.setMock(HttpCalloutMock.class, multiCalloutMock);
        ProcessAccountsContacts.processAccountsContacts();
        System.assertEquals(/*check for expected results here...*/);
    }
}

 

以上よろしくお願いいたします。