Developer

Test.setMockを使ったテストクラスの作成【セールスフォース】

Developer
この記事は約6分で読めます。

こんにちは、アンダーソンです。
今回はTest.setMockを使ったテストクラスの作成について書いていきたいと思います。

スポンサーリンク

Apexクラスの種類

まず、テストクラスを作成する対象のApexクラスによって、実装内容が変わります。

  • RESTコールアウトクラスであれば実装するMockはHttpRequestMock
  • SOAPコールアウトクラスであれば実装するMockはWebServiceMock
  • Webサービスクラスであれば実装するMockはなし

RESTなのか、SOAPなのかで実装するMockが変わりますので注意が必要です。

そもそもなぜMockクラスが必要なのかですが、
テストクラス及びメソッドではコールアウトの機能がないため、
実際のコードテストを行うことができません。
そこで擬似(Mock)的に呼び出したというステータスをsetして返却するクラスを作成しておきます。

HttpRequestMock

RESTコールアウトを実装しているクラスに対してTestクラスを作成する際は
HttpRequestMockを実装したMockクラスを作成し、擬似的にコールアウトして返却される
HeaderやBodyをsetします。

@isTest
public class ProjectCalloutServiceMock  implements HttpCallOutMock {
    public HttpResponse respond(HttpRequest reqesut){
        HttpResponse response = new HttpResponse();
        
        response.setHeader('Content-Type', 'application/json');
        response.setStatus('OK');
        response.setStatusCode(201);
        
        return response;
    }
}

このように返却されるステータスコードなども設定できますので、
テストではコールアウトが失敗した時などを想定したネガティブテストをすることもできます。
ちなみにメソッド名のrespondを変更するとエラーになります。
メソッド名は固定のようですね。

@isTest
static void testCorrect(){
    List<Opportunity> opps  = [SELECT Id,StageName FROM Opportunity WHERE Name = 'TestOpp'];
    for (Opportunity opp : opps){
        opp.StageName = 'Closed Won';
    } 
    
    Test.startTest();
    Test.setMock(HttpCalloutMock.class, new ProjectCalloutServiceMock());
    update opps;
    Test.stopTest();
    
    opps = [SELECT Id,StageName FROM Opportunity WHERE Name = 'TestOpp'];
    system.assertEquals('Submitted Project', opps[0].StageName);
}

※上記はあらかじめSetupメソッドでレコードを作成しています。

WebServiceMock

SOAPコールアウトを実装したクラスのテストでは
WebServiceMockを実装したテストクラスが必要になります。
WSDLからApexを作成した際にはWebServiceCallout.invokeから外部サービスへのコールアウトが実施されるため、Invokeが呼び出された際に擬似応答をするようにsetします。

@isTest
global class BillingCalloutServiceMock implements WebServiceMock  {
    
    global void doInvoke(
        Object stub,
        Object request,
        Map<String, Object> response,
        String endpoint,
        String soapAction,
        String requestName,
        String responseNS,
        String responseName,
        String responseType){
            BillingServiceProxy.billProjectResponse_element respElement = new BillingServiceProxy.billProjectResponse_element();
            
            respElement.status = 'OK';
            response.put('response_x',respElement);
        }
}

doInvokeメソッドを作成します。引数は固定で覚えておくといいと思います。
この例ではStatusにOKをセットして返すように設定しています。

@isTest
static void successTest(){
    List<Project__c> prjList = [SELECT Id,Status__c FROM Project__c WHERE Name = 'TestName'];
    for ( Project__c p : prjList ) {
        p.Status__c = 'Billable';
    }
       
    Test.startTest();
    Test.setMock(WebServiceMock.class,new BillingCalloutServiceMock());
    update prjList;
    Test.stopTest();
        
    prjList = [SELECT Status__c FROM Project__c WHERE Name = 'TestName'];
    system.assertEquals('Billable', prjList[0].Status__c);
}

メインのテストクラスはRESTの時と変わらないですね。
しっかりTest.setMockを使って呼び出されるようにしておきましょう。

まとめ

自分自身あいまいだったんですが、Data Integration Specialistのチャレンジの際に出てきたので
まとめてみました。
RESTはHTTP、SOAPはWebと覚えておくとよいかと思います。

その他の開発に関する記事はこちらです。

Developerも含めた試験問題にチャレンジしてみましょう。