Monday 21 October 2013

360° With Test Class for Beginners #Salesforce

Here is have provided some of the basics to write perfect test class in salesforce



Here I'll explain with short snippets for the test classes
As the first one below

1:  @isTest(seeAllData=false)  
2:    private class Test_CountContactOfAccount {   
3:      //Method  
4:      static testMethod void CountContactOfAccountUnitTest() {  
5:      }  
6:    }  

(seeAllData=false)
You can set it true or false on your own, there are two condition for setting it true or false

1. If you are querying any object and fetching records from the database in the test class then set it to true as well there are few object we can't create in our test like "OpportunityLineItem" so to test with this object records, we need to query it with "seeAllData = true".

2. But if you are inserting test records of an object an then querying it in the test class, then you need to set it false otherwise test class won't be executed.


TESTING CUSTOM CONTROLLER AND STANDARD CONTROLLERr
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

How to cover custom controller in the test class?
If you need to cover constructor in the test class then simply define it in the test class, like CountContactOfAccount is the name of the class, just define it in the test class as in below, it will cover you whole constructor.

1:  //Calling contructor  
2:  CountContactOfAccount controller = new CountContactOfAccount();  

How to call StandardController (ApexPages.StandardController stdController)?
If you are using standard controller in the class then you need to define it in the test class too

1:  //Insert you object that you are using in your class  
2:  Account acc = new Account(Name = 'test');  
3:  insert acc;  
4:  //Define standard controller and pass inserted object   
5:  ApexPages.StandardController stdController = new ApexPages.StandardController stdController(acc);  
6:  //Now define your controller then pass standard controller you've just defined  
7:  CountContactOfAccount controller = new CountContactOfAccount(stdController );  

TESTING WITH STATIC AND VOID METHODS
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

How to call methods in the test class?
As you have seen above we have called controller , by using controller we can call static and void methods easily

So if the method is void like "public void something() {"

1:    //Calling contructor  
2:    CountContactOfAccount controller = new CountContactOfAccount();  
3:    //Calling void method  
4:    controller.something();  

But if the method is static like "public static list something() {"

then you can directly call the method no need to use deifned controller

1:    //Calling static method  
2:    CountContactOfAccount.something(listOfAccount);   

TESTING ApexPages.currentPage().getParameters().get('ID')
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

In this scenario you just need to put the value in the test of the variable that you fetching from the the URL

1:  //this method will put Id in the URL in the test class  
2:  currentPageReference().getParameters().put('id', '001c384348247811');  

ASSERTS (Most Important thing for test classes)

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

There as three most commonly used asserts are there shown below, use asserts to check that your method are returning the correct values or not.

1:  System.assert(pBoolean)  
2:  System.assertEquals(pANY, pANY)  
3:  System.assertNotEquals(pANY, pANY)  

TESTING ERROR MESSAGES
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

If you have error message in your test class and you want to cover it in test class then use this snippet

1:  //List of Message  
2:  List msgs = ApexPages.getMessages();  
3:  //Define a boolean variable  
4:  boolean msg = false;  
5:  //Loop through the messages of the page  
6:  for(Apexpages.Message msg:msgs){  
7:  //if there is error message then set the boolean to true  
8:  if (msg.getDetail().contains(‘Search requires more characters’)) msg = true;  
9:  }  
10:  //Assert  
11:  system.assert(msg);  
12:  //Single Assert on Error Messages  
13:  System.assert(ApexPages.getMessages()[0].getDetail().contains( 'User not found with given username' ));  

I think these are the most common scenarios for the Test classes that makes some mess.

Some key points:

1. Whole orgs average code coverage should be 75%, NOT each class.
2. Each trigger must more then 0% code coverage.

Hope I've helped you
CHEERS....!!!!

Wednesday 9 October 2013

Populating Map Using Loops


Many times I faced that I need a Value with its "Group of values".
Getting a unique value in Set is a idea, but what if you have a group of values associated with it.

So that time Map is the best way to settle it down.
we can take Map in many ways but here I am using
Map<String, List<String>>

I used this map allot, because populating this map with Key and Values is a great method.
Here am showing two methods same but in different ways.

Here is the first one.

1:  //Map of Opportunity  
2:    Map<Id, Set<Id>> opportunityMap = new Map<Id, Set<Id>>();  
3:    //Loop through the Opportunity records  
4:    for(Opportunity opp : opportunities) {  
5:      //Check if map key contains System Field  
6:      if(opportunityMap.containsKey(opp.Opportunity_Field__c)) {  
7:       //Get the Values of the Map and add Id to it.  
8:       opportunityMap.get(opp.Opportunity_Field__c).add(opp.Id);  
9:      }else {  
10:       //Creat a new Set at values and add Id to it.  
11:       opportunityMap.put(opp.Opportunity_Field__c, new Set<Id>{opp.Id});   
12:      }  
13:     }  
14:    }  

Here is the same but another way to write it

1:  //Loop through list  
2:  for(Opportunity opp : opportunities) {  
3:    //List of Opportunity  
4:    List<Opportunity> opps = new List<Opportunity>();  
5:   //Check for values of the Map  
6:   &#160 if(mapOpportuinties.containsKey(opp.Fishbowl_Customer_Number__c) == false) {  
7:    //Add to list  
8:    opps.add(opp);  
9:   &#160} else {  
10:     //Add to list  
11:     opps = mapOpportuinties.get(opp.Fishbowl_Customer_Number__c);  
12:     opps.add(opp);  
13:   }  
14:     //Populating map  
15:     mapOpportuinties.put(opp.Fishbowl_Customer_Number__c, opps);  
16:   }  

Using the above snippet every unique value will have a common group of values. its like

Object1 = value1, value2 value3
Object2 = value1, value2, value3
Object3 = value2, value3, value4
Object4 = value5, value6, value7


Cheers....!!!!!
Happy Coding.

Thursday 3 October 2013

Send Email Using Trigger

Here I am using Trigger to send an email to the Contact, which don't have any associated Account.

There is a singleEmailMessage & MassEmailMessageclasses are provided by the Salesforce, which we can use to send an email or email in bulk to the users.

First of all we need to create a Helper class,we will call this class using Trigger, whenever the condition met, the trigger will call this Helper class, and all the stuffs whatever we are doing, will be in helper class. We are using an email template too.

This is an small an easy to understand Example.

Here is the Helper class named "HelperContactTrigger"

/**
* Description : Trigger to send email to the contact if accountId is null .
*
* Created By : Abhi Tripathi
*
* Created Date : 07/16/2013
*
* Revision Logs : V1.0
*
**/
public with sharing class HelperContactTrigger {

//static method
public static List sendEmail(List contacts) {

//query on template object
EmailTemplate et=[Select id from EmailTemplate where name=:'Sales: New Customer Email'];

//list of emails
List emails = new List();

//loop
for(Contact con : contacts){

//check for Account
if(con.AccountId == null && con.Email != null){

//initiallize messaging method
Messaging.SingleEmailMessage singleMail = new Messaging.SingleEmailMessage();

//set object Id
singleMail.setTargetObjectId(con.Id);

//set template Id
singleMail.setTemplateId(et.Id);

//flag to false to stop inserting activity history
singleMail.setSaveAsActivity(false);

//add to the list emails
emails.add(singleMail);
}
}

//send mail
Messaging.sendEmail(emails);

return contacts;
}
}

Now we will call the above class in our trigger named "SendEmailToAccount"
Here is the trigger, just paste this in your Account's Trigger

Trigger SendEmailToAccount on Contact (after insert, after update) {

if(Trigger.isAfter){
if(Trigger.isInsert || Trigger.isUpdate){

//helper class for single email but bulk messages
HelperContactTrigger.sendEmail(trigger.new);
}
}
}


Now you just need to create a Contact record and fill the Email field with your email and save it.
You will receive an email from the your salesforce.

Wednesday 2 October 2013

An Example of Email Services For Salesforce


Here am using Salesforce provided email services, where we can perform Dml processes on the basis of mails coming to the salesforce Org.

Salesforce generates its own email on which if user sends email, it is received by the associated Salesforce org.

To perform this whole action, need to create a EmailHandler class.

Here is the emailHandler class "UpdateAccountFromEmail"

 /**  
 * Description : Update Account's phone using Inbound Messages.  
 *  
 * Created By : Abhi Tripathi  
 *  
 * Version  : V1.0  
 *  
 * Revision Log : 10/01/2013 Created   
 **/  
 global class UpdateAccountFromEmail implements Messaging.InboundEmailHandler {  
   //Method to recieve email  
   global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {  
     //Instance of InboundEmailResult  
     Messaging.Inboundemailresult result = new Messaging.Inboundemailresult();  
     try{  
       //Strings  
       String phone = '';  
       String name = '';  
       //Text body  
       String accountTextBody = email.plainTextBody;   
       //Loop   
       for(String newStr : accountTextBody.split('\r\n')) {  
         //Get name values  
         name = newStr.substringAfter('Name:');  
         name = name.substringBefore('Phone:');  
         //Get phone value  
         phone = newStr.substringAfter('Phone:');  
         //Remove spaces  
         name = name.trim();  
         phone = phone.trim();  
         //List  
         List<string> phoneNumber = new List<string>();  
         //Loop through the String  
         for(String phn : phone.split('\n') ) {  
           phoneNumber.add(phn);  
         }  
         //Assigning value  
         phone = phoneNumber[0];  
       }  
       //Check fo name value  
       if(name != null || name != '') {  
         //Query on account  
         List<account> account = [Select Id From Account Where Name =: name];  
         System.debug('##### value of account' + account);  
         //Check for list size  
         if(account.size() != 0) {  
           //Assigning value to phone field  
           account[0].Phone = phone;  
           update account;   
         } else {  
           //If name is not found then create a new Account  
           Account acc = new Account();  
           acc.Name = name;  
           acc.Phone = phone;  
           insert acc;  
         }  
       }  
       //Set success to true    
       result.success = true;  
     }  
     //Excetion  
     catch(Exception e){  
       result.success=false;  
       result.Message='Unable to update your "Phone Number", Please try again.';  
     }  
     return result;  
   }  
 }  

Now we need to create our "Email Service"

Go to
Setup --> Develop --> Email Service

do as in below, in Apex Class field populate the name of the emailHandler class as marked, left Accept Email From blank, Click Save.


Now we can see the salesforce have generated an email id to which User can send email to Salesforce, as marked below


Now compose a mail, any of the email service as we had left the "Accept Email From" field blank, that will allow all the email services. Compose your email like this


After sending the above mail your Account will have a new record named "Test", or if you have already an Account named Test then it will update its phone field.