1

I have a HttpPost methods. And I really don't know how to test it correctly.

My methods:

public static App__c ParseRequest(RestRequest req) {
    App__c app = new App__c();
    String body = req.requestBody.toString();
    app = (App__c)JSON.deserialize(body, App__c.class);
    return app;  
} 

@HttpPost
global static Id doPost() {
    RestRequest req = RestContext.request;        
    App__c app = ParseRequest(req);
    insert app;
    return app.id;
}

My test (just basis):

public static String GenerateJSON(App__c a){
    Map<String, String> fieldMap = new Map<String, String>{'Title__c' => a.Name};       
    String serialized = JSON.serialize(fieldMap);         
    return serialized;
}

@isTest
static void testPost() {
    App__c record = createTestRecord();
    RestRequest request = new RestRequest();
    request.requestUri = System.URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/App__c/' + record.Id;
    request.httpMethod = 'POST';
    RestContext.request = request;

    record = (App__c)JSON.deserialize(GenerateJSON(record), App__c.class);

    App__c j = Endpoint.ParseRequest(request);
    record = (App__c)JSON.deserialize(body, App__c.class);
}

static App__c createTestRecord() {
    App__c app = new App__c(
        Title__c = 'Title',
    );
    insert app;
    return app;
}  

In App__c j = Endpoint.ParseRequest(request); I become Argument cannot be null. without coverage of:

    app = (App__c)JSON.deserialize(body, App__c.class);
    return app;  
} 

@HttpPost
global static Id doPost() {
    RestRequest req = RestContext.request;        
    App__c app = ParseRequest(req);
    insert app;
    return app.id;
}
2

The only real differences between testing an Apex webservice, and testing a "normal" Apex class is that you'll be providing input via RestContext.request, and gathering output via RestContext.response.

The following is an excerpt from one of my own tests for an Apex webservice in my org:

RestContext.request = new System.RestRequest();
RestContext.response = new System.RestResponse();
Map<String, String> headers = RestContext.request.headers;

headers.put('Content-Type', 'application/json');
RestContext.request.requestBody = Blob.valueOf('{}');

I set up the RestContext global...variable...thing with new instances of RestRequest and RestResponse, then store the request headers in a map.

Changes made to the headers map are automatically reflected in RestContext.request.headers (which is good, because I don't recall there being a setHeaders() method).

Finally, we set the request body (and we do need to directly assign this one), which accepts a blob. We can't construct a blob directly. We need to use the static method Blob.valueOf(String). In the test method that I took this code from, I'm testing what happens when my webservice receives a null object. Your test will likely be different.

Probably the easiest way for you to generate the JSON that you'll pass to the class you're testing is to create an in-memory instance of App__c (i.e. don't insert this record yourself in your test class, let the class being tested do the inserting).

App__c myTestApp = new App__c(
    some_field__c = 'value',
    other_field__c = 'something else'
);

String appJson = JSON.serialize(myTestApp);

Then you can swap in your JSON string where I have my empty JSON object in Blob.valueOf()

The other parts of unit testing remain the same. The only notes that I want to make here are that:

  1. You need to call the method you're testing, directly (i.e. explicitly call doPost())
  2. Take some time to think about what the effects of calling doPost() are, and write assertions (e.g. System.assertEquals()) to verify that all of those things are indeed happening

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.