Friday, 11 August 2017

WebServiceMock to test your Webservice Call

Salesforce is very flexible to integrate with other systems. In many projects we have lot of integrations of Salesforce with other systems. But main struggle starts while writing a test class for those integration webservices. 

Salesforce provides WebServiceMock interface to test Web service callouts of class auto-generated from a WSDL.

WebServiceMock methods:
  1. doInvoke(stub, soapRequest, responseMap, endpoint, soapAction, requestName, responseNamespace, responseName, responseType)

    • stub (Object) - An instance of the auto-generated class.
    • SoapRequest (object) - The SOAP Web service request being invoked.
    • responseMap (Map<String, Object>) - A collection of key/value pairs representing the response to send for the request.When implementing this interface, set the responseMap argument to a key/value pair representing the response desired.
    • endpoint (string) - The endpoint URL for the request.
    • soapPoint (String) - The requested SOAP operation. 
    • requestName (String) -  The requested SOAP operation name.
    • responseNameSpace (String) - Name of the response mentioned in WSDL.
    • responseType(String) - The class of the response mentioned in auto-generated class.

The methods in the auto-generated WSDL class call WebServiceCallout.invoke, which performs the callout to the external service. 
When testing these methods, you can instruct the Apex runtime to generate a fake response whenever WebServiceCallout.invoke is called. 
To do so, implement the WebServiceMock interface and specify a fake response for the Apex runtime to send. Here are the steps in more detail.

@isTest
global class WebServiceMockImpl 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) {
        


           webserviceClass.RequestRecipientTokenResponse reqTokem= new webserviceClass.RequestRecipientTokenResponse();
            reqTokem.RequestRecipientTokenResult = 'test';
            response.put('response_x', reqTokem);

}

Now in your actual test class just before calling your actual webservice invoke method, just instruct Apex runtime to send fake response by calling:

Test.setMock(WebServiceMock.class, new WebServiceMockImpl());         //At this line it is asking WebServiceMockImpl to generate fake response for invoke method defined in webserviceClass


You can use same WebServiceMockImpl class for multiple different calls. For that you have to use parameters of doInvoke() method to check what type of web service call has made.

For example:
Our WSDL class is:
       Gobal class docSample{

                                Public class DocSamplePort{
                                    public docSample.EnvelopeStatus CreateAndSendEnvelope(docSample.Envelope Envelope) {
                                                WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'http://www.docSample.net/API/3.0/SendEnvelope',
              'http://www.docSample.net/API/3.0',
              'SendEnvelope',
              'http://www. docSample.net/API/3.0',
              'SendEnvelopeResponse',
              docSample.SendEnvelopeResponse_element'}
                                                );
                                                }
                               


                                public String RequestSenderToken(String EnvelopeID,String AccountID,String ReturnURL) {
                                                WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'http://www.docSample.net/API/3.0/ RequestSenderToken,
              'http://www.docSample.net/API/3.0',
              'SendEnvelope',
              'http://www. docSample.net/API/3.0',
              'SendEnvelopeResponse',
              docSample. RequestSenderTokenResponse_element }
                                                );

                                }



   }

And our main class(let’s say docuSampleLanding.cls) calling these below webservices are:
1.     docSample. DocSamplePort es = dsApiSend.CreateAndSendEnvelope(DSEnvelope);

2.     token = dsApiSend.RequestRecipientToken(envelopeId, recipient_captiveinfo_ClientUserId, recipient_UserName, recipient_Email, assert, clientURLs);


While writing test class for docuSampleLanding.cls whenever your Apex runtime hits webservice call, it will give your error.
To avoid that just write below line of code:
Test.setMock(WebServiceMock.class, new WebServiceMockImpl()); 
And in WebServiceMockImpl class use multiple if statements t odetermine which web service call has been made.
For example:
global class WebServiceMockImpl 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) {

        if(requestName =='RequestRecipientToken'){
            docSample.RequestRecipientTokenResponse_element reqTokem= new docSample.RequestRecipientTokenResponse_element();
            reqTokem.RequestRecipientTokenResult = 'test';
            response.put('response_x', reqTokem);
        }
        if(requestName =='CreateAndSendEnvelope'){
             docSample.CreateAndSendEnvelopeResponse_element respElement = new docSample.CreateAndSendEnvelopeResponse_element();
      
               docSample.EnvelopeStatus es=new docSample.EnvelopeStatus();
               es.EnvelopeID='test';      
               respElement.CreateAndSendEnvelopeResult = es;
               response.put('response_x', respElement);

        }

}

No comments:

Post a Comment

Why to use Database.Stateful()?

Database Stateful is interface. It is used in batch classes to maintain the state of the class across transactions i.e. if you want to use ...