2

i'm trying to do a test method to cover a @HttpGet method. I'm pretty new on apex and i don't really understand how test (method/class) works for this kind of things.

Here is my method :

@RestResource(urlMapping='/invoicingWS')
global  class InvoicingWS {
public class WsException extends Exception {}

  @HttpGet
  global static void doInvoice() {
    RestContext.response.addHeader('Content-Type', 'application/json');
    try {
        Map<String,String> data = RestContext.request.params;
        if(!data.containsKey('companyID')) throw new WsException('companyID Missing');
        if(!data.containsKey('maxDate')) throw new WsException('maxDate Missing');

        Date maxDate = Date.valueOf(data.get('maxDate'));
        Date minDate;
        if(data.containsKey('minDate')) {
            minDate = Date.valueOf(data.get('minDate'));
            if(minDate > maxDate) throw new WsException('Input error: minDate > maxDate');
        }

        Id orderId  = [SELECT Id FROM Order WHERE Account.CompanyID__c = :data.get('companyID') LIMIT 1].Id;
        Invoicing_BuildInvoiceData x = new Invoicing_BuildInvoiceData(orderId, minDate, maxDate);
        Database.executeBatch(x);

        RestContext.response.responseBody = Blob.valueOf( '{ "status" : "success" }');
    } catch (QueryException d) {
        RestContext.response.responseBody = Blob.valueOf( '{ "status" : "error", "detail" : "Company does not exist"}');
    } catch (Exception e) {
        RestContext.response.responseBody = Blob.valueOf( '{ "status" : "error", "detail" : "'+e.getMessage()+'"}');
    }
  }
}

I tried to realize a corresponding test method but it does not work. Here is my work :

Test Method

    static testMethod void doInvoice(){

    RestRequest req = new RestRequest(); 
    RestResponse res = new RestResponse();

    req.requestURI = 'https:/services/apexrest/invoicingWS';
    req.addHeader('Content-Type', 'application/json');
    req.httpMethod = 'GET';
    req.requestBody = Blob.valueof('{}');

    RestContext.request = req;
    RestContext.response= res;

    InvoicingWS.doInvoice();

}

I know i miss so skills in Code coverage but i'm really not able to do it really quickly and that's why i request your help to do this.

Thanks in advance for answers

  • You need to add Mock class that implements HttpCalloutMock and in the test class add Test.setMock(HttpCalloutMock.class, new HttpMockTest()); – RCS May 11 '17 at 11:53
  • 2
    @VERYNET. FYI you do not need to use any mock interface to test a restresource method – Eric May 11 '17 at 13:16
  • So, what's not covered with you current work? Look at that and your code. Then add the things your code requires like maybe a maxDate param – Eric May 11 '17 at 13:18
  • @Eric you're right that's what i have done, and works perfectly. – VERYNET May 11 '17 at 13:29
4

You are actually really close... The short version is that you test your @RestResource Class just like you would any other Class.

  1. ARRANGE - setup the RestRequest & Instanciate the Class
  2. ACT - invoke the method, and capture the response in a local variable
  3. ASSERT - Run your assertions against the response local variable

(Don't need mocks for for Apex REST Resources, just for when calling a service outside of Salesforce)

static testMethod void test_doInvoice(){
    //ARRANGE - setup request like the external system would....
    RestRequest req = new RestRequest(); 
    RestResponse res = new RestResponse();
    InvoicingWS classToTest = new InvoicingWS();

    req.requestURI = 'https://cs84.salesforce.com/services/apexrest/invoicingWS';

    req.addHeader('Content-Type', 'application/json');
    req.httpMethod = 'GET';
    req.requestBody = Blob.valueof('{}');

    RestContext.request = req;
    RestContext.response= res;


    //ACT - make the request from inside the test execution context, rather than from the external system
    Test.startTest();
    res = classToTest.doInvoice();
    Test.stopTest();

    //ASSERT - verify that you got what you expected...
    String actualValue = res.getBody();
    String expectedValue = '{ "status" : "success" }'; //from your @HttpGet method above....
    System.assertEquals(actualValue, expectedValue);
    System.assertEquals(200, res.getStatusCode());

}
| improve this answer | |
  • Your code was good except fact that my doInvoice() method is a voice method. I simply used req.addparameters() to be able to test it. Thanks for replying – VERYNET May 12 '17 at 14:49
0

This is a full example that shows how to test an HTTP callout. The interface implementation (MockHttpResponseGenerator) is listed first. It is followed by a class containing the test method and another containing the method that the test calls. The testCallout test method sets the mock callout mode by calling Test.setMock before calling getInfoFromExternalService. It then verifies that the response returned is what the implemented respond method sent. Save each class separately and run the test in CalloutClassTest.

HttpCallout Mock Impl Class

@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        // Optionally, only send a mock response for a specific endpoint
        // and method.
        System.assertEquals('http://api.salesforce.com/foo/bar', req.getEndpoint());
        System.assertEquals('GET', req.getMethod());

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"foo":"bar"}');
        res.setStatusCode(200);
        return res;
    }
}

Callout Imp Class

public class CalloutClass {
    public static HttpResponse getInfoFromExternalService() {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://api.salesforce.com/foo/bar');
        req.setMethod('GET');
        Http h = new Http();
        HttpResponse res = h.send(req);
        return res;
    }
}

Test Class

@isTest
private class CalloutClassTest {
     @isTest static void testCallout() {
        // Set mock callout class 
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

        // Call method to test.
        // This causes a fake response to be sent
        // from the class that implements HttpCalloutMock. 
        HttpResponse res = CalloutClass.getInfoFromExternalService();

        // Verify response received contains fake values
        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');
        String actualValue = res.getBody();
        String expectedValue = '{"foo":"bar"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());
    }
}

For more details refer the salesforce link

| improve this answer | |
  • Look at my new TestMethod it acutally cover half of my apex code, it seems to be a good way to do it too. – VERYNET May 11 '17 at 13:01
  • 2
    You don't need to mock anything to test restresource methods. This is a good answer to a different question. In fact the whole point of mock is to not really send the fallout so even if you did it then it would never reach the restresource class. – Eric May 11 '17 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.