TrailHead

ApexでSOAPコールアウト【セールスフォース】

TrailHead
この記事は約11分で読めます。

今回は前回のRESTコールアウトに続いてSOAPコールアウトの単元をやっていきます。
前回に引き続き、Trailheadの内容に沿ってやっていけば問題なく回答できるチャレンジなんですが、
内容をしっかり理解して進んでいくことを目標にしましょう。

ではやっていきましょう!

Hands-on Challenge

Generate an Apex class using WSDL2Apex and write a test class.Generate an Apex class using WSDL2Apex for a SOAP web service, write unit tests that achieve 100% code coverage for the class using a mock response, and run your Apex tests.

  • Use WSDL2Apex to generate a class called ‘ParkService’ in public scope using this WSDL file. After you click the ‘Parse WSDL’ button don’t forget to change the name of the Apex Class Name from ‘parksServices’ to ‘ParkService’.
  • Create a class called ‘ParkLocator’ that has a ‘country’ method that uses the ‘ParkService’ class and returns an array of available park names for a particular country passed to the web service. Possible country names that can be passed to the web service include Germany, India, Japan and United States.
  • Create a test class named ParkLocatorTest that uses a mock class called ParkServiceMock to mock the callout response.
  • The unit tests must cover all lines of code included in the ParkLocator class, resulting in 100% code coverage.
  • Run your test class at least once (via ‘Run All’ tests the Developer Console) before attempting to verify this challenge.

日本語訳

WSDL2Apexを使用してApexクラスを生成し、テストクラスを記述します。
SOAP WebサービスのWSDL2Apexを使用してApexクラスを生成し、モック応答を使用してクラスの100%コードカバレッジを達成する単体テストを記述し、Apexテストを実行します。

  • WSDL2Apexを使用して、このWSDLファイルを使用してパブリックスコープで「ParkService」というクラスを生成します。 「WSDLの解析」ボタンをクリックした後、Apexクラス名の名前を「parksServices」から「ParkService」に変更することを忘れないでください。
  • 「ParkService」クラスを使用し、Webサービスに渡された特定の国の利用可能な公園名の配列を返す「country」メソッドを持つ「ParkLocator」というクラスを作成します。Webサービスに渡すことができる国名には、ドイツ、インド、日本、米国が含まれます。
  • ParkServiceMockというモッククラスを使用してコールアウト応答をモックするParkLocatorTestという名前のテストクラスを作成します。
  • ユニットテストは、ParkLocatorクラスに含まれるコードのすべての行をカバーする必要があり、その結果、コードカバレッジは100%になります。
  • この課題を検証する前に、テストクラスを少なくとも1回実行します(「すべて実行」を使用して開発者コンソールをテストします)。

解答

今回はthis WSDL fileこのファイルを取得した上で、クラスの作成、テストまでを行うって感じです。
ポイントは、

  • 「ParkService」と言うクラスを作成、使用してcountryメソッドを持った「ParkLocator」クラスを作成。
  • 「ParkServiceMock」「ParkLocatorTest」というテストクラスを作成しもちろんテストは100%ね。

こんな感じですね。まずはファイルの取得からいきましょう。
上記URLをクリックするとこんな画面が出てくるかと思います。

どうやってダウンロードするんだ?ってなったのでとりあえず全部コピーして
適当なテキストファイルにXML形式で保存しました。
次に保存したファイルを読み込ませてクラスの作成に移ります。

設定→開発→Apexクラス内のWSDLからの生成

を押します。
その中で先ほど作成したファイルを読み込ませましょう。

クラスの名前を変更するのを絶対に忘れないでください!!!

正しくはParkServiceです
これが出たらOKです!

※名前変更したはずなんですが、なぜかparksになってましたのでご注意です。

で、ParkLocator、ParkServiceMock、ParkLocatorTestをそれぞれ作っていきます。

ParkLocator

public class ParkLocator{
    public static List<String> country(String country){
        ParkService.ParksImplPort parks = new ParkService.ParksImplPort();
        List<String> parksName = parks.byCountry(country);
        
        return parksName;
    }
}

ParkServiceMock

@isTest
global class ParkServiceMock 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) {
        ParkService.byCountryResponse response_x = 
            new ParkService.byCountryResponse();
            
        List<String> stringList = new List<String> {'Park1','Park2','Park3'};
    
        response_x.return_x = stringList;
        response.put('response_x', response_x); 
   }
}

ParkLocatorTest

@isTest
private class ParkLocatorTest  {
    @isTest static void testCallout() {              
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        List<String> result = new List<String>();
        List<String> expectedvalue = new List<String>{'Park1','Park2','Park3'};
        
        result = ParkLocator.country('India');
    }
}

ParkLocatorにはString型のListでパークの名前を返却するというメソッドを作成しました。

あとはTrailhead内に出てきたものを同じように今回の形に変えていきました。
よし、これでいけるぞと思いきや、まさかのエラー。。。。

え、、、嘘でしょ。と時間だけが経過したので悔しいかな海外のサイト(検索したらそれしかなかった。)
に載ってたのでそこを見ながらやってみました。

で、まさかまさかのParkServiceクラスに間違いがあって、、、
てことで修正後のクラスが下記になります。
これで書き換えてコンパイルしたら通りました。
うーんTrailheadさん、頼むからよくわからんエラー出すのはほんまにやめて頂戴。。。

//Generated by wsdl2apex

public class ParkService {
    public class byCountryResponse {
        public String[] return_x;
        private String[] return_x_type_info = new String[]{'return','http://parks.services/',null,'0','-1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'return_x'};
    }
    public class byCountry {
        public String arg0;
        private String[] arg0_type_info = new String[]{'arg0','http://parks.services/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'arg0'};
    }
    public class ParksImplPort {
        public String endpoint_x = 'https://th-apex-soap-service.herokuapp.com/service/parks';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://parks.services/', 'ParkService'};
        public String[] byCountry(String arg0) {
            ParkService.byCountry request_x = new ParkService.byCountry();
            request_x.arg0 = arg0;
            ParkService.byCountryResponse response_x;
            Map<String, ParkService.byCountryResponse> response_map_x = new Map<String, ParkService.byCountryResponse>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              '',
              'http://parks.services/',
              'byCountry',
              'http://parks.services/',
              'byCountryResponse',
              'ParkService.byCountryResponse'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;
        }
    }
}

てことで合格。

この単元結構僕には難しいです。

コメント