+ Start a Discussion
Jeff Douglas (Personal)Jeff Douglas (Personal) 

How to unit test v24 Apex REST classes?

Perhaps I'm missing something here but I can't find any docs or way to write unit tests for Apex REST classes for v24. Here's my class:

 

@RestResource(urlMapping='/v.9/member/*/results/*') 
global with sharing class MemberRestSvc {
 
  @HttpGet
  global static String doGet() {
  
    String[] uriKeys = RestContext.request.requestURI.split('/');
    // do awesome programming stuff here

  }
    
}

 

With a v23, I would typically write a test like:

 

RestRequest req = new RestRequest(); 
RestResponse res = new RestResponse();
 
req.requestURI = 'https://cs9.salesforce.com/services/apexrest/v.9/member/me/results/today';  
req.httpMethod = 'GET';

String results = MemberRestSvc.doGet(req, res);
System.assertEquals('awesomeness-happened',results);

 

However, I can't figure out how to specify the requestURI. It looks like the the System.RestContext class is not writeable? I keep getting NPEs. Any help would be greatly appreciated.

 

Thanks

Jeff Douglas

Appirio / CloudSpokes

http://blog.jeffdouglas.com

Best Answer chosen by Admin (Salesforce Developers) 
logontokartiklogontokartik

Here is the code that is working for me. All you have to do is assign the RestRequest req to RestContext.request. 

@RestResource(urlMapping='/v.9/member/*/results/*') 
global with sharing class MemberRestSvc {
 
  @HttpGet
  global static String doGet() {
  
    String[] uriKeys = RestContext.request.requestURI.split('/');
    // do awesome programming stuff here
    system.debug('uriKeys' + uriKeys);
	return 'awesomeness-happened';
  }
    


	static testmethod void testMemberRestsvc(){
		
		RestRequest req = new RestRequest(); 
		RestResponse res = new RestResponse();
 
		req.requestURI = 'https://na14.salesforce.com/services/apexrest/v.9/member/me/results/today';  
		req.httpMethod = 'GET';
		RestContext.request = req;
		RestContext.response = res;
		String results = MemberRestSvc.doGet();
		System.assertEquals('awesomeness-happened',results);
		
	}
}

 

All Answers

logontokartiklogontokartik

Here is the code that is working for me. All you have to do is assign the RestRequest req to RestContext.request. 

@RestResource(urlMapping='/v.9/member/*/results/*') 
global with sharing class MemberRestSvc {
 
  @HttpGet
  global static String doGet() {
  
    String[] uriKeys = RestContext.request.requestURI.split('/');
    // do awesome programming stuff here
    system.debug('uriKeys' + uriKeys);
	return 'awesomeness-happened';
  }
    


	static testmethod void testMemberRestsvc(){
		
		RestRequest req = new RestRequest(); 
		RestResponse res = new RestResponse();
 
		req.requestURI = 'https://na14.salesforce.com/services/apexrest/v.9/member/me/results/today';  
		req.httpMethod = 'GET';
		RestContext.request = req;
		RestContext.response = res;
		String results = MemberRestSvc.doGet();
		System.assertEquals('awesomeness-happened',results);
		
	}
}

 

This was selected as the best answer
Pat PattersonPat Patterson

Not sure if this is a workaround, or the official way to do this, but you could code something like

 

@RestResource(urlMapping='/v.9/member/*/results/*') 
global with sharing class MemberRestSvc {
  private static String doGet(RestRequest req, RestResponse res) {
  
    String[] uriKeys = req.requestURI.split('/');
    // do awesome programming stuff here

  }
 
  @HttpGet
  global static String doGet() {
  
    return doGet(RestContext.request, RestContext.response);

  }
    
}

Your test code would then be something like:

 

RestRequest req = new RestRequest(); 
RestResponse res = new RestResponse();
 
req.requestURI = 'https://cs9.salesforce.com/services/apexrest/v.9/member/me/results/today';  
req.httpMethod = 'GET';

String results = MemberRestSvc.doGet(req, res);
System.assertEquals('awesomeness-happened',results);

try {
    // For coverage
    results = MemberRestSvc.doGet();
    // Should never get here
    System.assert(false);
} catch (NullPointerException npe) {
    // Should get here on the test
}

Cheers,

 

Pat

 

Pat PattersonPat Patterson

Looks like Kartik was working on this at the same time as me. If his version works for you, Jeff, it looks better than mine, but from your message, it sounded like you'd tried this approach unsuccessfully?

Kenji775Kenji775

My initial test seems to indicate that Kartik's solution works. Still verifying. 

bhuyadavbhuyadav

My solution is also same as kartik's solution. Thats the way to test v24 Apex Rest class.

mohith_shrivastavamohith_shrivastava

Do You guys have any idea whether now atleast can we utilize Winter 13 release mock callout methods for this ?

mandycmandyc

Hi Kartik,

 

Thank you for sharing your test code for a Get method. This is very helpful! Could you also post an example of a simple unit test for a Post method that accepts parameters in the request body?

 

Thanks in advance for your help.

logontokartiklogontokartik

Hello mandyc,

 

Set the req.addParameter and set the req.httpMethod to "POST', Below is the sample - 

        RestRequest req = new RestRequest(); // Build the REST Request for testing
      	req.addParameter('brand', 'brand1');
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = 'https://na11.salesforce.com/services/apexrest/v1.0/CaseService';
        req.httpMethod = 'POST';        // Perform a POST
        req.requestBody = Blob.valueof(JSONMsg); // Add JSON Message as a POST
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        CreateCaseSvc.doPost();

 

 

 

mandycmandyc

Thank you for your quick response! I'm getting the following error: Variable does not exist: JSONMsg.

logontokartiklogontokartik

You can mock the POST response message in JSONMsg

 

Something like

 

String JSONMsg = '{"message":"success"}';

mandycmandyc

I'm not having any luck. Here's my current error: Method does not exist or incorrect signature.

 

Here's my test code:

    static testMethod void testdoPost() {
        RestRequest req = new RestRequest();
        req.addParameter('firstname','Wain');
        req.addParameter('lastname','Rolen');
        req.addParameter('company','Test Company');
        req.addParameter('email','Wain@test.com');
        req.addParameter('phone','6884382997');
        req.addParameter('street','123 Test Ave');
        req.addParameter('city','Somewhere');
        req.addParameter('state','MA');
        req.addParameter('zip','87945');
        req.addParameter('country','US');
        req.addParameter('password','T3st789');
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = 'https://XXX.salesforce.com/services/apexrest/leads/';
        req.httpMethod = 'POST';
        String JSONMsg = '{"message":"success"}';
        req.requestBody = Blob.valueof(JSONMsg); // Add JSON Message as a POST
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        LeadRestSvc.doPost();
    } 

I'm wondering if I need to be using requestBody rather than addparameter given the below code?

global with sharing class LeadRestSvc {


    @HttpPost
    global static String doPost(String firstname, String lastname, String email, String password, String company, String phone, String street, String city, String state, String zip, String country) {
   //code here
   }
}

 

mohith_shrivastavamohith_shrivastava
static testMethod void testdoPost() {

        Lead l=new Lead();

        l.firstname='Wain';
        l.lastname='Rolen';
        l.company='Test Company';
        l.email='Wain@test.com';
        l.phone='6884382997';
        l.street='123 Test Ave';
        l.city='Somewhere';
        l.state='MA';
        l.zip='87945';
        l.country='US';
        l.password='T3st789';
        
        String JSONMsg= JSON.serialize(l);

        RestRequest req = new RestRequest();
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = '/services/apexrest/leads/';
        req.httpMethod = 'POST';
        
        req.requestBody = Blob.valueof(JSONMsg); // Add JSON Message as a POST
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        LeadRestSvc.doPost('Wain','colin'...fill all the parameters); }

 Please try the above .I hope this is clear and also use Test.Start Test and Test.Stop Test Methods for test classes as best practice.Thanks

mandycmandyc

Thank you, Mohith! Your example worked well for my doPost method.

 

Now I'm using your example to attend a test method for a doPatch call but having issues with the test code not firing. Here is my code if you have any suggestions.

 

    static testMethod void testdoPatch() {
 
        Lead l = new Lead();
    
        l.firstname = 'Wain';
        l.lastname = 'Rolen';
        l.company = 'Test Company';
        l.email = 'Wain@test.com';
        l.phone = '6884382997';
        l.street = '123 Test Ave';
        l.city = 'Somewhere';
        l.state = 'MA';
        l.PostalCode = '87945';
        l.country = 'US';
        l.Self_Service_Password__c = 'T3st789';
        insert(l);
        String recordId = l.sample_Id__c;
        
        String JSONMsg = JSON.serialize(l);
        
        RestRequest req = new RestRequest();
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = '/services/apexrest/v.1/leads/' + recordId;
        req.httpMethod = 'PATCH';
        
        req.requestBody = Blob.valueof(JSONMsg); // Add JSON Message as a POST
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        LeadRestSvc.doPatch('Wain','Rolen','Wain@test.com','6884382997','12345 Test Ave','Somewhere','MA','87945','US'); 
    }  

 

mohith_shrivastavamohith_shrivastava

Please paste the class for PATCH call.I will have a look .Thanks.Please Mark as answer for POST call as that may help others .

mandycmandyc

Here is the PATCH call:

    @HttpPatch
    global static String doPatch(String firstname, String lastname, String email, String phone, String street, String city, String state, String zip, String country) {
    
    RestRequest req = RestContext.request;
    
    // see if a wicell_id was part of the uri
    String sample_id = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
    
    if (sample_id != '') {
        Savepoint sp = Database.setSavePoint();
    
        try {
            
            Contact[] contactToUpdate = [SELECT Id FROM Contact WHERE Sample_Id__c =: sample_id];
            if(contactToUpdate.size() > 0){
                for(Contact c : contactToUpdate){
                    c.FirstName = firstname;
                    c.LastName = lastname;
                    c.Email = email;
                    c.Phone = phone;
                    c.MailingStreet = street;
                    c.MailingCity = city;
                    c.MailingState = state;
                    c.MailingPostalCode = zip;
                    c.MailingCountry = country;
                }
                update contactToUpdate;     
            }
            else {
                Lead[] leadToUpdate = [SELECT Id FROM Lead WHERE IsConverted = false AND Sample_Id__c =: sample_id];
                if(leadToUpdate.size() > 0){
                    for(Lead l : leadToUpdate){
                        l.FirstName = firstname;
                        l.LastName = lastname;
                        l.Email = email;
                        l.Phone = phone;
                        l.Street = street;
                        l.City = city;
                        l.State = state;
                        l.PostalCode = zip;
                        l.Country = country;
                    }
                    update leadToUpdate;
                }    
            } 
            return sample_id;
        }
        catch (DMLException e1) {
            Database.rollback(sp);
            return e1.getDMLMessage(0);
        }
        catch (Exception e2) {
            Database.rollback(sp);
            return e2.getMessage();
        }
    }
    else {
        return 'Invalid operation';
    }
  }

Below is the latest test code for the PATCH call. Note, I'm getting the following error: List has no rows for assignment to SObject on the following line about half way through the below code: String orgId = [SELECT Id from Account LIMIT 1].Id;

 

I have @isTest listed at the top of my class.

    static testMethod void testdoPatch() {
 
        Lead l = new Lead();
    
        l.firstname = 'Wain';
        l.lastname = 'Rolen';
        l.company = 'Test Company';
        l.email = 'Wain@test.com';
        l.phone = '6884382997';
        l.street = '123 Test Ave';
        l.city = 'Somewhere';
        l.state = 'MA';
        l.PostalCode = '87945';
        l.country = 'US';
        insert(l);
        String sample_Id = l.Sample_Id__c;
        
        String JSONMsg = JSON.serialize(l);
        
        RestRequest req = new RestRequest();
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = 'https://cs4.salesforce.com/services/apexrest/v.1/leads/' + sample_Id;
        req.httpMethod = 'PATCH';
        
        req.requestBody = Blob.valueof(JSONMsg); // Add JSON Message as a POST
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        LeadRestSvc.doPatch('Wain','Rolen','Wain@test.com','6884382997','12345 Test Ave','Somewhere','MA','87945','US'); 
        
        //Test doPatch for contacts
        String orgId = [SELECT Id from Account LIMIT 1].Id;
        
        Contact c = new Contact();
    
        c.firstname = 'Wain';
        c.lastname = 'Rolen';
        c.AccountId = orgId;
        c.email = 'Wain@test.com';
        c.phone = '6884382997';
        c.mailingstreet = '123 Test Ave';
        c.mailingcity = 'Somewhere';
        c.mailingstate = 'MA';
        c.mailingPostalCode = '87945';
        c.mailingcountry = 'US';
        c.Sample_Id__c = sample_Id;
        insert(c);
        String contactSampleId = c.Sample_Id__c;
        
        String JSONMsg2 = JSON.serialize(c);
        
        RestRequest req2 = new RestRequest();
        req2.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req2.requestURI = 'https://cs4.salesforce.com/services/apexrest/v.1/leads/' + contactSampleId;
        req2.httpMethod = 'PATCH';
        
        req2.requestBody = Blob.valueof(JSONMsg2); // Add JSON Message as a POST
        
        RestResponse res2 = new RestResponse();
        RestContext.request = req2;
        RestContext.response = res2;
        LeadRestSvc.doPatch('Wain','Rolen','Wain@test.com','6884382997','12345 Test Ave','Somewhere','MA','87945','US');
    }

I tried to mark your earlier response as the answer but I wasn't given the option. Maybe this is due to a different post being marked as the answer by another user?

 

Thank you for your help!!!

mohith_shrivastavamohith_shrivastava

Insert the account in your test class .And then the exception will disappear

mandycmandyc

Thank you, Mohit! That solved the problem.

 

Most of my PATCH code is not being tested. I think it's because I'm creating new lead and contact records in the tests but then the following lines do not return anything for the new test sample_ids I'm sending.

 

Contact[] contactToUpdate = [SELECT Id FROM Contact WHERE Sample_Id__c =: sample_id];
Lead[] leadToUpdate = [SELECT Id FROM Lead WHERE IsConverted = false AND Sample_Id__c =: sample_id];

 

mandycmandyc

Here is a screen shot of the patch code (click "Test Code" hyperlink) that is not being fired by my test code (included below). Does anyone have thoughts around why line 68 is returning false?

 

Test Code

 

Here is my test code:

    static testMethod void testdoPatch() {
     //create new order
 
        //Create New Account (Org) Record to link to Opportunity
        Account newAcct = new Account();
        newAcct.Name = 'Bubba Gump Shrimp Co';
        newAcct.RecordTypeId = '012500000005HjFAAU';
        insert(newAcct);
        Id OrgId = newAcct.Id; 
        
        //Create New Account (Org) Record for TTO
        Account newAct = new Account();
        newAct.Name = 'Company';
        newAct.RecordTypeId = '012500000005HjFAAU';
        newAct.Agreement_Company_Code__c = 'W';
        insert(newAct);        
        
        //Create New Contact Record to link to Account
        Contact newCon = new Contact();
        newCon.FirstName = 'Tommy';
        newCon.LastName = 'Tuckerr';
        insert(newCon);
        Id ContactId = newCon.Id;         
 
        //Create New Opportunity Record
        Id oppRT = [SELECT Id FROM RecordType WHERE SobjectType = 'Opportunity' and IsActive = True LIMIT 1].Id;

        Opportunity newOpp = new Opportunity();
        newOpp.AccountId = OrgId;
        newOpp.Licensing_Organization__c = OrgId; //'0015000000LQdcMAAT';
        newOpp.Opportunity_Number__c = 'D09-J0001';
        newOpp.RecordTypeId = oppRT;
        newOpp.Name = 'OPPORTUNITY NAME';
        newOpp.StageName = 'Initial Contact/Exploration';
        newOpp.CloseDate = date.Today() + 30;
        newOpp.Clone_Flag__c = True;
        newOpp.Agreement_Clone_ID__c = 'a0750000002zlJYAAY';
        insert(newOpp);
        Id NewOppId = newOpp.Id;
         
        //Create New Order Record
        Id orderRT = [SELECT Id FROM RecordType WHERE SobjectType = 'Order__c' and IsActive = True LIMIT 1].Id;
        Order__c odr = new Order__c();
        odr.RecordTypeId = orderRT;
        odr.Name = '9998989';
        odr.Opportunity_Name__c = NewOppId;
        odr.Status__c = 'Open'; //'Opportunity Created';
        odr.Account__c = OrgId;
        odr.Contact__c = ContactId;
        insert(odr);
        String odrID = odr.Name;
        
        RestRequest req = new RestRequest();
        req.addHeader('Content-Type', 'application/json'); // Add a JSON Header as it is validated
        req.requestURI = 'https://cs4.salesforce.com/services/apexrest/v.1/orders/' + odrID +'/';
        req.httpMethod = 'PATCH';
        
        RestResponse res = new RestResponse();
        RestContext.request = req;
        RestContext.response = res;
        OrderRestSvc.doPatch();  
    } 

 

 

azu.shaik1.3965080575576013E12azu.shaik1.3965080575576013E12
Hi friends ,

I need the delete method for the Apex rest class : Please provide sample code