SalesforceBlue

Feel the rhythm of Salesforce

Apex

Apex Unit Tests Simplified

To facilitate the development of robust, error-free code, Apex supports the creation and execution of unit tests.

Below are few of the common reasons to write Apex Unit Test:

  • Meet the Salesforce 75% minimum code coverage requirement.
  • Validate that the functionality of the code whether it is working as expected.
  • Can the code handle bulk operations by doing Bulk Testing.
  • Does the Changes made to the existing code base impacting the present system i.e. Regression Testing

Unit tests are class methods that verify whether a particular piece of code is working properly.

Unit test methods take no arguments, commit no data to the database, and send no emails.

Such methods are flagged with the @isTest annotation in the method definition.

Unit test methods must be defined in test classes, that is, classes annotated with @isTest.

Apex Unit Test Basic Code Block:

@isTest
private class myClass {
    @isTest static void myTest() {
        // code_block
    }
}

Classes and methods defined as @isTest can be either private or public. The access level of test classes methods doesn’t matter. You need not add an access modifier when defining a test class or test methods.

The default access level in Apex is private. The testing framework can always find the test methods and execute them, regardless of their access level.

Classes defined as @isTest must be top-level classes and can’t be interfaces or enums.

Methods of a test class can only be called from a test method or code invoked by a test method; non-test requests can’t invoke it.

Creating Test Data Using Test Setup Methods:

Use test setup methods (methods that are annotated with @testSetup) to create test records once and then access them in every test method in the test class. Test setup methods can be time-saving when you need to create reference or prerequisite data for all test methods, or a common set of records that all test methods operate on.

The following example shows how to create test records once and then access them in multiple test methods. Also, the example shows how changes that are made in the first test method are rolled back and are not available to the second test method.

@isTest
private class CommonTestSetup {

    @testSetup static void setup() {
        // Create common test accounts
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i));
        }
        insert testAccts;        
    }
    
    @isTest static void testMethod1() {
        // Get the first test account by using a SOQL query
        Account acct = [SELECT Id FROM Account WHERE Name='TestAcct0' LIMIT 1];
        // Modify first account
        acct.Phone = '555-1212';
        // This update is local to this test method only.
        update acct;
        
        // Delete second account
        Account acct2 = [SELECT Id FROM Account WHERE Name='TestAcct1' LIMIT 1];
        // This deletion is local to this test method only.
        delete acct2;
        
        // Perform some testing
    }

    @isTest static void testMethod2() {
        // The changes made by testMethod1() are rolled back and 
        // are not visible to this test method.        
        // Get the first account by using a SOQL query
        Account acct = [SELECT Phone FROM Account WHERE Name='TestAcct0' LIMIT 1];
        // Verify that test account created by test setup method is unaltered.
        System.assertEquals(null, acct.Phone);
        
        // Get the second account by using a SOQL query
        Account acct2 = [SELECT Id FROM Account WHERE Name='TestAcct1' LIMIT 1];
        // Verify test account created by test setup method is unaltered.
        System.assertNotEquals(null, acct2);
        
        // Perform some testing
    }

}
Apex Unit Test Example:

Please create the following Apex Class in your Salesforce dev org for which we would be creating a test class:

public with sharing class AccountController {
    @AuraEnabled
    public static List<Account> getAccounts() {
        List<Account> accList = [
            SElECT Id, Name, AnnualRevenue 
            FROM Account 
            WHERE 
            AnnualRevenue > 100000 LIMIT 10
        ];

        if(! accList.isEmpty()) {
            return accList;
        } else {
            return null;
        }
    }
}

In the above class we have created a method which will be returning 10 accounts having annual revenue more than $100000.

Below is the respective test class created for this Apex class:

@isTest
private with sharing class AccountControllerTest {
    @TestSetup
    static void makeTestAccounts(){
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i, AnnualRevenue = 2000000));
        }

        insert testAccts;
    }

    @isTest 
    static void getAccountTest() {
        List<Account> accList = AccountController.getAccounts();
        System.assert(accList !=null, True);
    }
}

In the above test class we have created first a test setup method makeTestAccounts() to generate test data.

Later we have created the test method getAccountTest() to test the AccountController.getAccounts() behaviour.

Running Apex Unit Tests:

Locate the test class which you have created and click on Run Test button.


View Test Class Execution Status:

Once you click on the Run Test button you will be rediercted to the Apex Test Execution Page where you can check the status of your running test classes.


Apex Unit Tests Considerations:
  • Starting with Salesforce API 28.0, test methods can no longer reside in non-test classes and must be part of classes annotated with isTest. See the TestVisible annotation to learn how you can access private class members from a test class.
  • Test methods can’t be used to test Web service callouts. Instead, use mock callouts. See Test Web Service Callouts and Testing HTTP Callouts.
  • You can’t send email messages from a test method.
  • Since test methods don’t commit data created in the test, you don’t have to delete test data upon completion.
  • If the value of a static member variable in a test class is changed in a testSetup or test method, the new value isn’t preserved. Other test methods in this class get the original value of the static member variable. This behavior also applies when the static member variable is defined in another class and accessed in test methods.
  • For some sObjects that have fields with unique constraints, inserting duplicate sObject records results in an error. For example, inserting CollaborationGroup sObjects with the same names results in an error because CollaborationGroup records must have unique names.
  • Tracked changes for a record (FeedTrackedChange records) in Chatter feeds aren’t available when test methods modify the associated record. FeedTrackedChange records require the change to the parent record they’re associated with to be committed to the database before they’re created. Since test methods don’t commit data, they don’t result in the creation of FeedTrackedChange records. Similarly, field history tracking records can’t be created in test methods because they require other sObject records to be committed first. For example, AccountHistory records can’t be created in test methods because Account records must be committed first.
  • If your tests include DML, make sure that you don’t exceed the MAX_DML_ROWS limit.

Thank you for visiting SalesforceBlue.com
If you have any queries feel free to write down a comment below 🙂


Leave a Reply

Your email address will not be published. Required fields are marked *