Showing posts with label @isTest. Show all posts
Showing posts with label @isTest. Show all posts

Tuesday, November 20, 2018

Asynchronous Apex: Queueable Apex in Salesforce.com

Queueable Apex

The best features of Queueable Apex is job chaining. If you ever need to run jobs sequentially, Queueable Apex is only option.

To chain a job to another executing job, submit the second_job by using execute() method of your queueable class. You can add only one job from an executing job, which means that only one child job can exist for each parent job. 

For example, if you have a second class called Second_Job that implements the Queueable interface, you can add this class to the queue in the execute() method as follows:

Queueable Syntax:

public class SomeClass implements Queueable { 
    public void execute(QueueableContext context) {
        //awesome code here
    }
}

Chaining Jobs:

public class FirstQueClass implements Queueable { 

    public void execute(QueueableContext context) { 

        // Awesome processing logic here   
        // Chain this job to next job by submitting the next job
        System.enqueueJob(new Second_Job());

    }
}


Note: Once again, testing has a slightly different pattern. You can’t chain queueable jobs in an Apex test, doing so results in an error. 
To avoid errors, you can check if Apex is running in test context by calling Test.isRunningTest() before chaining jobs.

Scenario 1:

The following apex code takes a collection of Account records, sets the parentId for each record, and then updates the records in the database.


public class UpdateParentAccountQue implements Queueable {

    private List<Account> accounts;
    private ID parent;

    public UpdateParentAccount(List<Account> records, ID id) {

        this.accounts = records;
        this.parent = id;
    }

    public void execute(QueueableContext context) {

        for (Account account : accounts) {
        account.parentId = parent;
        
        //perform other processing or callout
        
        }
        update accounts;
    }  
}


Add this class as a job on the queue

//find all accounts in ‘NY’
List<Account> accounts = [select id from account where billingstate = ‘NY’];

//find a specific parent account for all records
Id parentId = [select id from account where name = 'ACME Corp'][0].Id;

//instantiate a new instance of the Queueable class
UpdateParentAccount updateJob = new UpdateParentAccount(accounts, parentId);

//enqueue the job for processing
ID jobID = System.enqueueJob(updateJob);

Monitor progress either through the Apex Jobs page or programmatically by querying AsyncApexJob.

SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID

Test Class:

@isTest
public class UpdateParentAccountTest {

    @testSetup 
    static void setup() {
        List<Account> accounts = new List<Account>();
        // add a parent account
        accounts.add(new Account(name='Parent'));
        // add 100 child accounts
        for (Integer i = 0; i < 100; i++) {
            accounts.add(new Account(
                name='Test Account'+i
                ));
        }
        insert accounts;
    }
    
    static testmethod void testQueueable() {
     //Query for test data to pass to queueable class
     Id parentId = [Select Id From Account Where Name = 'Parent'][0].Id;
     List<Account> accounts = [Select Id, Name From Account Where Name Like 'Test Account%'];
     //Create our Queueable instance
     UpdateParentAccount updater = new UpdateParentAccount(accounts, parentId);
     //Test.startTest() and Test.stopTest() block to force async processes to run
    Test.startTest();        
        System.enqueueJob(updater);
    Test.stopTest();        
     //Validate the job ran. Check if record have correct parentId now
     System.assertEquals(100, [select count() from account where parentId = :parentId]);

    }

}











Thursday, November 8, 2018

Best Practices for writing Apex Test Class in Salesforce.com

Best Practices for writing Apex Test Class

1) Use @isTest keyword to declare apex test class and methods.

2) Use @testSetup to set up test data required for testing.

3) Use @TestVisible in apex controller method defined as private, so it can be accessed in test class.

4) Use System.runAs(user) to test apex on profile level.

5) Avoid using SeeAllData = true because it allows test methods to access database records for testing, resulting it can fail in production where database not having corresponding records.

Note: Only use SeeAllData = true, if there are sObjects that doesn't allow DML operation. e.g. PriceBook creation.

6) Use Test.startTest and Test.stopTest to reset the governor limit, and also to forces the asynchronous methods to execute synchronously, so that the results can be asserted.

7) Use System.assertEquals(expected, actual, msg) and System.assertNotEquals(expected, actual, msg) to assert expected and actual values from test methods.

8) Avoid Hard Code Ids of any sObject in any test method.

9) Use Null Pointer Exception test as part of negative testing for each method, specially the methods which takes parameters.


Test class important keywords are 
  • @isTest
  • @testSetup
  • @TestVisible
  • System.runAs(user)
  • SeeAllData = true
  • Test.startTest and Test.stopTest
  • System.assert(condition, msg)
  • System.assertEquals(expected, actual, msg)
  • System.assertNotEquals(expected, actual, msg)









Validation in flow input text field in sfdc: Maximum 255 characters limit

The input text field validate in sfdc flow behaves opposite of the generic sfdc validation rule.  Here the validation formula is evaluating ...