Tuesday, May 31, 2016

APEX: Access History Programatically

For Standard Objects:
AccountHistory
ContactHistory
OpportunityHistory

For Custom Objects:
MyCustomObject__History

Example:
1. Select Id, Name, (Select OldValue, NewValue From Histories) From MyObject__c [1]

2. Select ParentId, OldValue, NewValue, Field, CreatedById, CreatedDate From MyObject__History [2]

[1] http://salesforce.stackexchange.com/questions/17057/how-to-track-history-of-a-record-of-a-custom-object-in-apex-classhttp://salesforce.stackexchange.com/questions/17057/how-to-track-history-of-a-record-of-a-custom-object-in-apex-class

[2] https://developer.salesforce.com/forums/?id=906F0000000937RIAQ

APEX: Access Sharing Programatically

For Standard Objects:
AcountShare
ContactShare
OpportunityShare
.......

For Custom Objects:
MyCustomObject__Share

Properties:
AccessLevel
ParentID
RowCause
UserOrGroupdId

Examples:
MyCustomObject__Share myObj = new MyCustomObject__Share();

myObj.AccessLevel = 'Read';

myObj.ParentID = someId;

myObj.RowCause = Schema.MyCustomObject__Share.Manual;

myObj.UserOrGroupId = someUserOrGroupId;

For more information: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm

Friday, May 27, 2016

APEX: Web Service Callouts using WebServiceMock

1. Implement the WebServiceMock 

@isTest
global class MyWebServiceCalloutMock implements WebServiceMock
{
    // Need to override this method
    global void doInvoke(
                   Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType)
    {
        try
        {
             MyService.myElement test = MyService.MyElement();
             MyElement.Result = 'Test';
       response.put('response_x', test); 
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
        return res;
     }
}


2. Create the test class
@isTest
public class WebServiceTest 
{
     public static testMethod void testRestGetService() 
     {
        try
        {
           Test.startTest();
             Test.setMock(WebServiceMock.class, new MyWebserviceCalloutMock());
        
             String response = MyCalloutClass.processService('Test');
        
             // provide your assertions here

           Test.stopTest();
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
    }
}
This is the sample Callout Class public class MyCalloutClass { public static String processService(String input) {
        try
        {
          MyService.MyElement elm = new MyService.MyElement();
          elm.endpoint_c = 'your endpoint url';
          return elm.myServiceMethod(input);
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); 
        }
        return '';
    }
}

This is a sample generated class
public class MyService
{
    public class MyElement
    {
       public static String Result;
       public String myServiceMethod(String input)
       {
           // Autogenerated code here
       }
    }
}

You can find more information to the original article here: 
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_testing.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_gen_code.htm

APEX: HTTP Callouts Testing using HttpCalloutMock

So far, we have seen a simple way for testing REST services in a single test method http://programmersrealm.blogspot.com/2016/05/creating-tests-for-rest-services-in.html

However, there may be times when we don't want to hit the actual server. Isolating our testing in our environment is ideal and crucial to catch any errors before testing in the real environment.

As a best practice, we can use the HttpCalloutMock Interface that Salesforce provides out of the box.
This will help us provide fake responses in our test class.

1. Implement the HttpCalloutMock

@isTest
global class MyHttpCalloutMock implements HttpCalloutMock
{
    // Need to override this method
    global HTTPResponse respond(HTTPRequest req)
    {
        try
        {
           HttpResponse res = new HttpResponse();
           res.setHeader('Content-Type', 'application/json');
           res.setBody('{"myvar":"myvalue"}');
           res.setStatusCode(200);
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
        return res;
     }
}


2. Create the test class
@isTest
public class RestServiceTest 
{
     public static testMethod void testRestGetService() 
     {
        try
        {
           Test.startTest();
             Test.setMock(HttpCalloutMock.class, new MyHttpCalloutMock());
        
             HttpResponse res = MyCalloutClass.processGetService();
        
             // provide your assertions here

           Test.stopTest();
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
    }
}
This is the sample Callout Class public class MyCalloutClass { public static HttpResponse processGetService() { try { HttpRequest req = new HttpRequest(); req.setEndpoint('http://yourendpoint/myvar/myvalue'); req.setMethod('GET'); Http h = new Http(); HttpResponse res = h.send(req); } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } return res; } }

You can find more information to the original article here: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

Friday, May 20, 2016

APEX: Mixed DML Operations Error

You get the following exception or similar: "Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object:  Product2"

In this case, you need to enclose your setup object in a system.runAs() operation as follows:

system.runAs(new User(Id = UserInfo.getUserId())) 
{
    ...your setup-object DML...
    User usr = new User();
    usr.UserName = 'Test';
    .....
    insert usr;
}

Thursday, May 19, 2016

APEX: Instantiating a Constructor with a StandardController Parameter in a Test Class

Suppose you have the following class:

public with sharing class MyClass {
public MyClass(ApexPages.StandardController con) { try { if(con != null) { // your sObject and any other logic here Account acct = (Account)con.getRecord(); } } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } } public void myMethod(){} }

Then in your test class:
public static testMethod void testMyClass() { try { Test.startTest(); // Create sObject in your own factory class List<Account> accts = TestFactory.createSObject('Account', 1, true); system.assertEquals(accts.size(), 1); PageReference pr = Page.MyPage; Test.setCurrentPageReference(pr);
        ApexPages.currentPage().getParameters().put('qp', 'yyyy');
MyClass mc = new MyClass(new ApexPages.StandardController(accts.get(0))); Test.stopTest(); } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } }

Tuesday, May 17, 2016

jQuery: DOM Element not loaded even when using $(document).ready()

DOM Element may not be loaded yet due to an external library being used, or the page loading time is taking too long. 

I'm not a big fan of timeouts, but if you have a better solution, please let me know.


Solution:
Check if the element is loaded, if not, set a timeout to load the element.


<script> jQuery(document).ready(getUsers); function getUsers() { var elm = jQuery(".leftPanel").find("#rowheader0"); if (elm[0]) { alert(jQuery(".leftPanel").find("#rowheader0").text()); } else { // Wait a bit longer setTimeout(getUsers, 50); } } </script>

APEX: Creating Tests for Rest Services in Apex using GET

Suppose you have the following rest service in your org:

@HttpGet global static Object getObject() { Map<String, String> paramMap = RestContext.request.params; String param1Value = paramMap.get('param1'); }

How do you test the above code snippet?
In your test class, you need to provide the parameters as follows:

// Initialize both response and request from the service to be called
RestRequest rReq = new RestRequest(); RestResponse rRes = new RestResponse(); // The Service we want to access rReq.requestURI = url.getSalesforceBaseUrl().toExternalForm() + '/MyRestServiceURL/'; // The parameter(s) we want to pass to the service rReq.addParameter('param1', 'some value'); // Service method rReq.httpMethod = 'GET'; // Service Context objects ready RestContext.request = rReq; RestContext.response = rRes; // Call Service Object myObj = MyRestService.getObject();

APEX: Creating Person Accounts in Salesforce using Apex

If your current org supports Person Accounts, you will need to let Salesforce know that you want to create Person Accounts and not Business Accounts.

First option is to query the RecordType object as follows:

List<RecordType> rType = [Select Id, Name From RecordType Where name = 'Person Account' 
and sobjectType = 'Account'];

This is pretty straightforward.  However, if your client decides to customize the Name for the record type (i.e. Person Accounts 2), the above query is not longer flexible.

Second option is to query the RecordType object using the IsPersonType field as follows:

List<RecordType> rType = [Select Id, Name, sobjectType, IsPersonType From RecordType 
Where IsPersonType = true and sobjectType = 'Account'];

Finally, you will need to create the Person Account as follows:

Account acct = new Account(); acct.RecordTypeId = rType .get(0).Id; acct.LastName = 'Test';