Step by Step Salesforce Tutorial – Creating Trigger and Test cases – 6 of 6

Get articles everyday as a email directly to your inbox:
Click to publicize, if you like this article :

This is the last tutorial in series and we will see that how to create a Trigger and Test Cases in salesforce.

A trigger is an Apex script that executes before or after specific data manipulation language (DML) events occur, such as before object records are inserted into the database, or after records have been deleted.

Triggers are stored as metadata in Salesforce.com. A list of all triggers in your organization is located at SetupDevelopApex Triggers. In addition to this list, triggers are associated and stored with specific objects.

To define a trigger:

  1. For a standard object, click SetupCustomize, click the name of the object, then click Triggers.For a custom object, click SetupCreateObjects and click the name of the object.For campaign members, click SetupCustomizeCampaignsCampaign MemberTriggers.For case comments, click SetupCasesCase CommentsTriggers.

    For email messages, click SetupCasesEmail MessagesTriggers.

  2. In the Triggers related list, click New.
  3. Click Version Settings to specify the version of Apex and the API used with this trigger. If your organization has installed managed packages from the AppExchange, you can also specify which version of each managed package to use with this trigger. Generally, you should use the default values for all versions. This associates the trigger with the most recent version of Apex and the API, as well as each managed package. You can specify an older version of a managed package if you want to access components or functionality that differs from the most recent package version. You can specify an older version of Apex and the API to maintain specific behavior.
  4. Select the Is Active checkbox if the trigger should be compiled and enabled. Leave this checkbox deselected if you only want to store the script in your organization’s metadata. This checkbox is selected by default.
  5. In the Body text box, enter the Apex for the trigger. A single trigger can be up to “1 million” characters in length.

Read this URL for Governor limit reference.

To define a trigger, use the following syntax:

trigger triggerName on ObjectName (trigger_events) {
   code_block
}

where trigger_events can be a comma-separated list of one or more of the following events:

  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

So, lets start with creating trigger.

I want that duplicate student should not be created on the basis of Email id. we can achieve this by other way also, like during creation of email field, we can specify it as unique field.

Open eclipse and right click on salesforce project and select Create new Trigger, as shown in below image

Creating Trigger in Salesforce using force.com IDE

Creating Trigger in Salesforce using force.com IDE

As you can see, to create trigger we have to select the Apex version and operations in wizard.

During Trigger creation, keep in mind that it may be required in bulk operations so governor limit may be problem.

So instead of getting query for all triggers individually, I created an array and after that created a set of email entered for all records, and loop through all records invidually and checked for duplicity.
Only one SOQL is fired instead of all triggers individually and thus can work for bulk insert.

For SOQL Best Practice refer :
http://wiki.developerforce.com/index.php/Best_Practice:_Avoid_SOQL_Queries_ Inside_FOR_Loops

trigger DuplicateStudentCheck on Student__c (before insert) {

       //Get all Student__c related to the incoming Student records in a single SOQL query.
       Student__c[] studentsList = Trigger.new;
       Set emailSet = new Set();
       for(Student__c s : studentsList)
       {
       	emailSet.add(s.Email__c);
       }

       //Get list of duplicate Students
       List duplicateStudentList = [Select s.Name, s.Email__c From Student__c s
where s.Email__c IN :emailSet];

       Set duplicateEmailIds = new Set();

       for(Student__c s : duplicateStudentList)
       {
       	duplicateEmailIds.add(s.Email__c);
       }

       for(Student__c s : studentsList)
       {
       	    if(duplicateEmailIds.contains(s.Email__c))
       	    {
       	    	s.Email__c.addError('Record already exist with same email Id');
       	    }
       }
}

Note: You can add, edit, or delete Apex using the Salesforce.com user interface only in a Developer Edition organization, a Salesforce.com Enterprise Edition trial organization, or sandbox organization. In a Salesforce.com production organization, you can only make changes to Apex by using the Metadata API deploy call, the Force.com IDE, or theForce.com Migration Tool. The Force.com IDE and Force.com Migration Tool are free resources provided by salesforce.com to support its users and partners, but are not considered part of our Services for purposes of the salesforce.com Master Subscription Agreement.

Test Cases in Salesforce :


Test case integral part of code developement.

  • You must have at least 75% of your Apex scripts covered by unit tests to deploy your scripts to production environments. In addition, all triggers should have some test coverage.
  • Salesforce.com recommends that you have 100% of your scripts covered by unit tests, where possible.
  • Calls to
    System.debug are not counted as part of Apex code coverage in unit tests.

So, here we are going to create Test Case for trigger which we have written:

@isTest
private class TestTriggers {

    static testMethod void myUnitTest() {
        Student__c s = new Student__c();
        s.Name = 'Om Test';
        s.l_Name__c = 'LastName';

        Course__c c = new Course__c();
        c.Name = 'SFDC';
        c.Fees__c = 2000;
        insert c;

        s.Course__c = c.Id;
        s.Installment_1__c = 2000;
        s.Email__c = 'admin@shivasoft.in';
        try
        {
        	insert s;
        }
        catch(System.DMLException e)
        {
        	System.assert(e.getMessage().contains('Record already exist with same email Id'));
        }
    }
}

To run the test case from Eclipse, right click on test class as shown in below image:

Run Test Case using Eclipse in Salesforce

Run Test Case using Eclipse in Salesforce

The output of the test case, Test coverage result:

Test Coverage result Eclipse in Salesforce

Test Coverage result Eclipse in Salesforce

Run test cases from salesforce.com browser:

click SetupDevelopApex Classes, click the name of the class, then click Run Test. If your class calls another class or causes a trigger to execute, those Apex scripts are included in the total amount used for calculating the percentage of code covered.

To run all the unit tests in your organization, click SetupDevelopApex Classes, then click Run All Tests.

Possibly Related posts:

  1. Step by Step Salesforce Tutorial – Creating custom object – 1 of 6
  2. Step by Step Salesforce Tutorial – Creating Email Template – 4 of 6
  3. Step by Step Salesforce Tutorial – Creating Tab and Validation Rule – 3 of 6
  4. Step by Step Salesforce Tutorial – Creating fields – 2 of 6
  5. Step by Step Salesforce Tutorial – Creating Workflow rule – 5 of 6
You can leave a response, or trackback from your own site.
  • Sakshigandhi261

    hii,
     plzz tel me another way to write error message in triger except this:
    trigger test on Account (before insert) {
    trigger.new[0].name.addError(‘Nice try’);
    }

    • JitendraZaa

      Hi,
      Either you can add error message at field level or object level.

      Your code explains the field level, below example is at object level:

      trigger test on Account (before insert) {trigger.new[0].addError(‘Nice try’);} 

  • Ravikumaru007

     how to generate Mr. before all records using apex trigger.

    plz… send me code for my mail     ravikumaru007@gmail.com

  • Amarnagumanni

    which language is the relation of salesforce

  • Lakshmi Sf6

    sorry the other one is luxmi085@gmail.com

  • Lakshmi Sf6

    hi 
    i am Lakshmi
    I started learning salesforce
    i completed ECE ,bcz of electronics dept im not able to understand your code
    i am poor in programming,
    i want to learn apex language
    could u pls provide me some material
    in sales force for developer what should i need to learn
    i am unable to understand triggers code
    provide me some simple examples  or material to understand.
    i am afraid of coding and programming, but i wish to learn it and to get ajob in salesforce as a developer,
    my mail id : lakshmi.sf6@gmail.com 
                      luxmi85@gmail:disqus.com

    Thanks & Regards
    lakshmi.

    • Surendrak188

       there are many videos uploaded in you tube as a beginner to the sales force you can get some basic  idea later u can go fr documentation hopes it helps u

      Regards,
      Surendra

  • Arun

    07204651195

  • http://twitter.com/mjgallag24 Michael Gallagher

    @58580936bae722b65524173157e34bc3:disqus in looking at your code, I’m fairly certain that if I insert two students with the same email address, in the same batch, it will allow them both to be inserted

    • Anonymous

      Hey Michael,
      Thanks for reviewing the code.
      I have tested code and its working fine. Any reason or bug you find in above code?

      • http://twitter.com/mjgallag24 Michael Gallagher

        Hi Jitendra,
        I’m referring to batch DML, for example something like:insert new Student__c[]{new Student__c(Email__c=’notInDatabase@ notInDatabase.com’), new Student__c(Email__c=’notInDatabase@ notInDatabase.com’)};
        Both student records will be inserted into the database at the same time, as part of the same batch, with duplicate email addresses. See what I mean now?
        Regards,
        Mike

        • Anonymous

          Yeah.. You are right. I am comparing with existing records only and skipped the condition to check duplicate email Id within batch.

          Thank you so much for your time.

          Regards,
          Jitendra Zaa

  • Ashish yadav

    A single trigger can be up to 32,000 characters in length is wrong its 1 million not 32000 please correct

    • http://shivasoft.in Jitendra Zaa

      Thanks Ashish for pointing it out. It was 32,000 at the time when i wrote this article. Now its updated.

      Regards,
      Jitendra Zaa

  • Himanshu

    nope

  • Himanshu

    It works fine in apex page but on native page it doesn’t come as html

  • HImanshu

    I am facing one issue. I want to show trigger error message as html for example. I have following code

    c.addError(‘cannot be rejected through this screen.click < a href="#" rel="nofollow" >here< /a > to Approve/Reject’);

    But it shows as normal text without any hyperlink.

    • http://shivasoft.in Jitendra Zaa

      Hi Himanshu,
      It works perfectly. Check below code snap:

      trigger AddLinkInError on Student__c (before insert) {
      Student__c[] studentsList = Trigger.new;
      for(Student__c s : studentsList )
      {
      s.adderror('< a href = \' www.shivasoft.in \ ' > This is Test < / a >. ');
      }
      }

      Regards,
      Jitendra Zaa

    • http://shivasoft.in Jitendra Zaa

      Hi Himanshu,
      Any luck on this problem ?

      Regards,
      Jitendra Zaa

  • priya

    Hi Jitendra,

    I was getting the error only when i tried with ‘Date’.So when i try giving like this,

    CREATEDDATE=\’9/5/2011 12:00:00 AM\’

    i was getting the same error.

  • priya

    Hi Jitendra,
    i just want to make sure is this the format u’ve suggested while fetching from sfdc?

    CREATEDDATE=\’9/5/2011 12:00:00 AM\’

    Regards,
    Priya

    • http://shivasoft.in Jitendra Zaa

      Yes,
      Example –
      global final String gstrQuery = ‘SELECT ID, StageName, Designated_Contact_Count__C from Opportunity where StageName != \’Expired\”;

      Please reply that it worked or not?
      Regards,
      Jitendra Zaa

  • priya

    am getting this error,no viable alternative at character ” when i try fetching records from salesforce.Any help would be greatly appreciated.

    • http://shivasoft.in Jitendra Zaa

      Hi Priya,
      Instead of double quotes (“) , use single Quotes (‘)
      OR
      in SOQL query use escape sequence – instead of (‘) use (\’)

      Regards,
      Jitendra Zaa

  • omni

    Error: Compile Error: expecting a right parentheses, found ‘status__c’ at line 5 column 17

  • omni

    now this error

    Error: Compile Error: line 5:17 no viable alternative at character ‘’’ at line 5 column 17

  • omni

    this is the code

    trigger trg on position__c (after insert,after update)
    {

    position__c ps = [ select Remainings__c,Openings__c from position__c];
    if(trigger.new(0)status__c==’recruited’)
    {
    ps.Remainings__c = ps.Openings__c – 1;
    }
    update ps;

    }

    nd the error i get isError: Compile Error: expecting a right parentheses, found ‘status__c’ at line 5 column 17

    • http://shivasoft.in Jitendra Zaa

      Hi try below code :

      trigger trg on position__c (after insert,after update)
      {

      position__c ps = trigger.new[0];
      if(ps.status__c==’recruited’)
      {
      ps.Remainings__c = ps.Openings__c – 1;
      }
      update ps;

      }

  • http://shivasoft.in Jitendra Zaa

    Hi Omni,
    If Both object are in relation then u can use “before Trigger” on object (position).

    Thanks,
    Jitendra Zaa

  • omni

    ohk sir i need to update my object(position) no_of_openings__c which is a picklist whn the status STATUS=recruited of another object (job application)
    no_of_openings__c=Remainings__c-1; how do i proceed im a newbie

  • Narasimha

    Ya its good!
    Thanku so much.

    • http://shivasoft.in Jitendra Zaa

      Thanks Narasimha.

  • sreekanth

    nice info, thanks a lot its very useful..

  • http://shivasoft.in admin

    Hi Cloud-Ling,
    Please try this:

    trigger ErrorDuplicateOutput on Account (before insert, before update)
    {
    List accList = Trigger.New;

    Set b = new Set{‘Express Logistics and Transport’,’Edge Communications’};

    for (Account acc1 : accList)
    {
    if (b.contains(acc1.Name))
    {
    acc1.Name.addError(‘This is error Message’);
    }
    }
    update accList;
    }

    /*
    * You cannot add error message in existing object, you can add message on object on which operation is performed.
    */

    Thanks,
    Jitendra Zaa

  • Cloud-Ling

    Hi, thanks for your post, it’s really helpful especially with newbies like me. How come my addError method doesn’t come up with it should’ve done?
    here’s the error message every time i try my code

    Apex trigger ErrorDuplicateOutput caused an unexpected exception, contact your administrator: ErrorDuplicateOutput: execution of BeforeInsert caused by: System.FinalException: SObject row does not allow errors: Trigger.ErrorDuplicateOutput: line 11, column 5

    here’s my code where I compiled with no errors,

    trigger ErrorDuplicateOutput on Account (before insert, before update)
    {
    List accList =new List();
    Set b = new Set{‘Express Logistics and Transport’,'Edge Communications’};
    accList = [Select Id, Name FROM Account Where Name in: b];

    for (Account acc : accList)
    {
    if (b.contains(acc.Name))
    {
    acc.Name.addError(”);
    }
    }
    update accList;
    }

    your help will be very much appreciated!
    Cloud-Ling