Salesforce 使用Apex调用外部数据的接口有两种方式:SOAP 和 REST
- SOAP:Web服务使用XML格式的文件调用服务器,通常需要WSDL文档来生成代码
- REST:HTTP使用REST格式的文件调用服务器,推荐使用
基于WSDL的CallOut适用于SOAP方式,HTTP方式可以使用任何的HTTP Service,SOAP或者REST都可以,推荐使用REST方式. 在使用SOAP方式调用接口时,可以借助WSDL2Apex工具将XML文件生成Apex类
- 在Setup上搜索 Apex Classes
- 点击Generate From WSDL
- 选择文件parks.xml
- 点击Parse WSDL,通过WSDL2Apex工具生成ParkService类和AsyncParkService类
- 点击Generate Apex code,确认生产Apex文件
- 点击Done
Tips:WSDL解析器很可能因为各种奇怪的原因导致生成文件失败,这时就需要手动调整Apex类或者XML文件,非常的不友好. 正确生成的两个类,一个用于同步调用外部的Web服务(ParkService),一个用于异步调用外部的Web服务(AsyncParkService)
调用外部Web接口的时候,都需要将服务器接口地址添加到远程站点列表进行认证,Setup → Remote Site Settings,添加站点“https://th-apex-soap-service.herokuapp.com”
//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; } } }
在成功生成Apex类后,即可尝试调用接口查询数据
public class ParkLocator { // 测试数据可以是:Germany, India, Japan and United States public static String[] country(String country){ ParkService.ParksImplPort parkImp = new ParkService.ParksImplPort(); String[] parkList = parkImp.byCountry(country); System.debug('parkList:' + parkList); return parkList; } }
和Rest接口一样,普通的测试类不支持Web服务的接口,因此,需要做一些额外工作来进行测试类的编写
新建一个模拟服务器返回数据的类: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(); response_x.return_x = new String[]{'Yellowstone', 'Mackinac National Park', 'Yosemite'}; // 结束 - response.put('response_x', response_x); } }
然后创建测试类:ParkLocatorTest
@isTest public class ParkLocatorTest { @isTest static void testCallout() { // 产生模拟的服务器响应数据 Test.setMock(WebServiceMock.class, new ParkServiceMock()); // 调用接口方法 String[] result = ParkLocator.country('Japan'); } }
Salesforce Apex提供了内置的WebServiceMock接口和Test.setMock方法,用以测试方法接收虚假服务器响应,从而提供必要的测试类覆盖范围
参考数据: