0

I'm learning how to write tests for my code and trying to figure what needs to be tested with a custom controller. It seems like maybe nothing but maybe I'm just not thinking about it in the right way. Take the constructor for example:

global with sharing class myCustomController {

    public String clientId {get; set;}
    public String UserId {get; set;}
    public Map<String, Map<String, String>> allFieldData {get; set;}
    public String allFieldDataJSON {get{return JSON.serialize(allFieldData);}}
    public String assetEndpoint {get; set;}

    public myCustomController() {
        String settingId = [SELECT Id FROM Organization][0].Id;
        UserId = UserInfo.getUserId();
        allFieldData = new Map<String, Map<String, String>>();
        CustomSetting__c userSettings;
        userSettings = [SELECT client_id__c, asset_endpoint__c FROM CustomSetting__c WHERE setupownerid = :settingId][0];
        clientId = userSettings.client_id__c;

        if(userSettings.asset_endpoint__c != null){
            assetEndpoint = userSettings.asset_endpoint__c;
        }
        List<String> objectsToQuery = new List<string>{ 'Account', 'Lead', 'Contact', 'Opportunity' };
        for(String objectToQuery : objectsToQuery){
            allFieldData.put(objectToQuery, getFieldsForSelectedObject(objectToQuery));
        }
    }

}

In this I have the following components:

settingId - this is basically the Org ID that I use for custom settings. I assume I don't need to test this in any way

UserId - this is the userId of the currently logged in user, I use this to obtain their email address, I assume I don't need to test this

allFieldData - This is schema information from the database, again, don't need to test (right?)

userSettings - These are populated when the user installs the app. Is there some test I should run here on them?

objectsToQuery - This is some schema information from the database. Doesn't seem like there's any tests to run here?

assetEndpoint - This is pulled from the custom settings, if it exists. Doesn't need a test right?

1
  • One principle is that you should only test the required behaviour of the controller not internal detail that could change and still leave the controller working. So use local variables and private variables as much as possible and only use @TestVisible is exceptional circumstances: looks like you are already doing that. Note that global isn't right in most cases; use public. – Keith C Jul 8 '16 at 8:30
1

Well, testing is all about creating a re-runnable regression testbed that asserts the correct functionality of the class and as a side effect, covers the code so it can be deployed. Since you don't know who (including yourself) will muck with code in the future, creating a testmethod provides a statement of application correctness and helps prevent against inadvertent changes with unintended side effects.

So, with a slightly rewritten controller

Controller (using properties more than constructor logic)

global with sharing class myCustomController {

  public String clientId {get {return CustomSetting__c.getOrgDefaults().client_id__c}; }
  public String UserId   {get {return UserInfo.getUserId();} }
  public Map<String, Map<String, String>> allFieldData {
     get{
        if (this.allFieldData == null) {
            this.allFieldData = new map<String,String> ();
            for (String objectToQuery : new List<string>{ 'Account', 'Lead', 'Contact', 'Opportunity' };){
                allFieldData.put(objectToQuery, getFieldsForSelectedObject(objectToQuery));
        }
  }
  public String allFieldDataJSON {get{return JSON.serialize(allFieldData);}}
  public String assetEndpoint {get {return CustomSetting__c.getOrgDefaults().asset_endpoint__c;} set;}

 public myCustomController() {
 }
}

Test method

private static void testMyCustomController() {
    // Mock org-wide custom setting

    myCustomController ctlr = new myCustomController() {
    System.assertNotEquals(null, ctlr.clientId);
    System.assertEquals(UserInfo.getUserId(), ctlr.UserId);  // arguable why a property for this at all 
    System.assert(ctlr.allFieldData.get('Account').length() > 0,'verify some fields were returned');
    System.assert(ctlr.allFieldDdataJSON.length() > 0,'some serialization must occur');
    }
}

To your specific questions:

settingId - this is basically the Org ID that I use for custom settings. I assume I don't need to test this in any way

Rewritten controller avoids need to test this

UserId - this is the userId of the currently logged in user, I use this to obtain their email address, I assume I don't need to test this

UserInfo.getUserEmail() accomplishes this - no need to verify it. Personally, I'd ditch the property UserId

allFieldData - This is schema information from the database, again, don't need to test (right?)

This relies on some other method you have getFieldsForSelectedObject(..). That method does need testing. In my example, I test it indirectly because I don't know what it does in detail.

userSettings - These are populated when the user installs the app. Is there some test I should run here on them?

You need to mock the user settings - from the constructor, it looks like you always used org settings. So I coded appropriately

objectsToQuery - This is some schema information from the database. Doesn't seem like there's any tests to run here?

Rewritten controller avoids any need to test this variable as variable removed.

assetEndpoint - This is pulled from the custom settings, if it exists. Doesn't need a test right?

Nope - your code will either have null or non-null value here. The controller as shown above doesn't care

0

This is my findings, it may vary from person to person.

Whenever we test some functionality we need to create sample test data which may include user, custom settings data, records etc.

Some cases like profiles, organization details we directly query from the org. So settingId will always return value.

UserId - The test scenarios and outcome varies based on the user who is executing the functionality, thats why we follow System.runAs(user). If an user does not have access to a particular object he will not able to see or access data.

allFieldData - Thinking a scenario like you need to have a custom field in Lead object. You have given System.assert() with that field. Now when you deploy the change set in new org if that field does not exist then the test will fail.

userSettings - If the data returns empty then your this code clientId = userSettings.client_id__cwill fail. So thats need to be tested.

objectsToQuery - It will also return values as these are standard objects.

assetEndpoint - Tts need to be tested with positive and negative scenarios for custom settings data.

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.