Saturday 20 October 2012

Testing Web Service Callouts

In Winter 13, Generated code is saved as an Apex class containing the methods you can invoke for calling the Web service. To deploy or package this Apex class and other accompanying code, 75% of the code must have test coverage, including the methods in the generated class. By default, test methods don’t support Web service callouts and tests that perform Web service callouts are skipped. To prevent tests from being skipped and to increase code coverage, Apex provides the built-in WebServiceMock interface and the Test.setMock method that you can use to receive fake responses in a test method.

Auto-generated apex class from WSDL


//Generated by wsdl2apex 
    

public class docSample {

    public class EchoStringResponse_element {

        public String EchoStringResult;

        private String[] EchoStringResult_type_info = new String[]{
                            'EchoStringResult',
                            'http://www.w3.org/2001/XMLSchema',
                            'string','0','1','false'};

        private String[] apex_schema_type_info = new String[]{
                            'http://doc.sample.com/docSample',
                            'true'};

        private String[] field_order_type_info = new String[]{
                            'EchoStringResult'};
    }

    public class DocSamplePort {

        public String endpoint_x = 'http://YourServer/YourService';

        private String[] ns_map_type_info = new String[]{
                             'http://doc.sample.com/docSample', 
                             'docSample'};

        public String EchoString(String input) {
            docSample.EchoString_element request_x = 
                               new docSample.EchoString_element();
            docSample.EchoStringResponse_element response_x;
            request_x.input = input;
            Map response_map_x = 
                      new Map();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
                 'urn:dotnet.callouttest.soap.sforce.com/EchoString',
                 'http://doc.sample.com/docSample',
                 'EchoString',
                 'http://doc.sample.com/docSample',
                 'EchoStringResponse',
                 'docSample.EchoStringResponse_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.EchoStringResult;
        }
    }

    public class EchoString_element {

        public String input;
        private String[] input_type_info = new String[]{
                                 'input',
                                 'http://www.w3.org/2001/XMLSchema',
                                 'string','0','1','false'};
        private String[] apex_schema_type_info = new String[]{
                                 'http://doc.sample.com/docSample',
                                 'true'};
        private String[] field_order_type_info = new String[]{'input'};
    }
}


Web Service Callouts class

Class

public class WebSvcCallout {
    public static String callEchoString(String input) {
        docSample.DocSamplePort sample = new docSample.DocSamplePort();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class 
    
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}


First, implement the WebServiceMock interface and specify the fake response in the doInvoke method.

Test Class

@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       docSample.EchoStringResponse_element respElement = new docSample.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}


Test class of Web Service Callouts class

Test Class

@isTest
private class WebSvcCalloutTest {
    @isTest static void testEchoString() {              
        // This causes a fake response to be generated 
    
        Test.setMock(WebServiceMock.class, new WebServiceMockImpl());
        
        // Call the method that invokes a callout 
    
        String output = WebSvcCallout.callEchoString('Hello World!');
        
        // Verify that a fake result is returned 
    
        System.assertEquals('Mock response', output); 
    }
}

10 comments:

  1. yes... impressive cut and paste from the Winter '13 release notes

    ReplyDelete
    Replies
    1. Yes. Felt like I had seen it somewhere!

      Delete
  2. It looks like the mock method needs an instance of the web service DTO class (docSample.EchoStringResponse_element).

    Our web services are part of a third party library. We could do with mocking them (or mocking the third party library if possible) but don't have the DTO class. We do have the WSDL so I wonder if we make our own DTO class it will work?

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Thank you for sharing valuable information. Nice post. I enjoyed reading this post. The whole blog is very nice found some good stuff and good information here Thanks..Also visit my page Starter SEO Package

    ReplyDelete
  5. Blogger considered web 2.0 and provides you space to post your blogs. these blog posts links could be shared on different Data sharing websites like , Social Bookmarking websites, Forums, Groups and different social media marketing websites. seo company used these ways can increased highest visibility and improves keywords ranking in search engines.

    ReplyDelete
  6. Hi, right now am writing test code for my webservice, i just don't get if i have to write a method for every method i have on my webservice. wha i have to do here?

    ReplyDelete
  7. @msalazar I am in same situation. Have you found a way to write test class for more than one apex callouts?

    ReplyDelete