function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
travis.truetttravis.truett 

Test/Publish Trigger

I wrote a fairly simple Apex trigger in my company's sandbox that I want to roll out, but I don't understand how testing and code coverage work. Is there a way I can specifically just test my trigger and get salesforce to let me publish it?

Thanks
Jim RaeJim Rae
There are several good examples of test methods in the apex developer guide, but the short answer is yes.
Your test method will need to create a record or records of the object type from your trigger, and then perform the DML action the trigger is looking for. After you do the DML in your test, then you should requery the record you created and validate that the trigger did what it was supposed to do.
Amit Chaudhary 8Amit Chaudhary 8
Hi travis.truett,

Please check below blog for more information on Test classes:-
http://amitsalesforce.blogspot.in/2015/06/best-practice-for-test-classes-sample.html

Test Class for Trigger 
@isTest 
public class TriggerTestClass 
{
    static testMethod void testMethod1() 
 {
  // Perform DML here only
 
        }
}

Test Class for Standard Controller
@isTest 
public class ExtensionTestClass 
{
 static testMethod void testMethod1() 
 {
 Account testAccount = new Account();
 testAccount.Name='Test Account' ;
 insert testAccount;

 Test.StartTest(); 
  ApexPages.StandardController sc = new ApexPages.StandardController(testAccount);
  myControllerExtension testAccPlan = new myControllerExtension(sc);

  PageReference pageRef = Page.AccountPlan; // Add your VF page Name here
  pageRef.getParameters().put('id', String.valueOf(testAccount.Id));
  Test.setCurrentPage(pageRef);

  //testAccPlan.save(); call all your function here
 Test.StopTest();
 }
}

Please let us know if this will help you
 
travis.truetttravis.truett
So here's my trigger. It adds schedule items to Opportunity Products when they're created. I guess I'm just confused as to what things I should be testing from my trigger:

trigger editSchedule on OpportunityLineItem (after insert) {

if(Trigger.isInsert){

Map<Id, Opportunity> opportunities = new Map<Id, Opportunity>();
Date myDate = Date.newInstance(1990, 2, 17);

for(OpportunityLineItem oli: Trigger.new) {
    opportunities.put(oli.OpportunityId, null);
}
opportunities.putAll([SELECT CloseDate FROM Opportunity WHERE Id in :opportunities.keySet()]);
for(OpportunityLineItem oli: Trigger.new) {
     Opportunity thisLineItemOpp = opportunities.get(oli.OpportunityId);
     myDate = thisLineItemOpp.CloseDate;
      
}

List<OpportunityLineItemSchedule> listOLIS = new List<OpportunityLineItemSchedule>();

for (OpportunityLineItem oli: Trigger.new){

if(oli.PricebookEntryId == '01uU000000H81Iv' || oli.PricebookEntryId == '01uU000000H81Iy'){//These are the Pricebook Entry IDs of Onboarding and Training, our two services. 
                                                                                           //They must be handled differently than the products, because their list price 
                                                                                           //is one sum, as opposed to a monthly amount. In order to get this trigger to handle
                                                                                           //new services, insert their IDs into each if statement for handling services.    

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = 943, ScheduleDate = myDate, Type = 'Revenue'));

}


    if(oli.Payment_Terms__c == 'Monthly'){
    
    if(oli.PricebookEntryId == '01uU000000H81Iv' || oli.PricebookEntryId == '01uU000000H81Iy'){
    
for(Integer duration = (Integer)oli.Duration__c; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = (oli.Discounted_Price__c*oli.Quantity)/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(1);

}//end of loop
    
    }//end of inner IF
    
else{
for(Integer duration = (Integer)oli.Duration__c; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = oli.Discounted_Price__c*oli.Quantity, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(1);

}//end of loop

}//end of else

}//end of Monthly IF


    else if(oli.Payment_Terms__c == 'Quarterly'){
    
         if(oli.PricebookEntryId == '01uU000000H81Iv' || oli.PricebookEntryId == '01uU000000H81Iy'){
    
for(Integer duration = (Integer)oli.Duration__c/3; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = (oli.Discounted_Price__c*oli.Quantity*3)/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(3);

}//end of loop
    
    }//end of inner IF

else{
for(Integer duration = (Integer)oli.Duration__c/3; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = oli.Discounted_Price__c*oli.Quantity*3, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addMonths(3);

}//end of loop

}//end of else

}//end of Quarterly IF


    else if(oli.Payment_Terms__c == 'Annually'){
    
         if(oli.PricebookEntryId == '01uU000000H81Iv' || oli.PricebookEntryId == '01uU000000H81Iy'){
    
for(Integer duration = (Integer)oli.Duration__c/12; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = (oli.Discounted_Price__c*oli.Quantity*12)/oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addYears(1);

}//end of loop
    
    }//end of inner IF

else{
for(Integer duration = (Integer)oli.Duration__c/12; duration > 0; duration--){

listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = oli.Discounted_Price__c*oli.Quantity*12, ScheduleDate = myDate, Type = 'Revenue'));
myDate = myDate.addYears(1);

}//end of loop

}//end of else

}//end of Annually IF


    else if(oli.Payment_Terms__c == 'Up Front'){
    
         if(oli.PricebookEntryId == '01uU000000H81Iv' || oli.PricebookEntryId == '01uU000000H81Iy'){
    
listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = oli.Discounted_Price__c*oli.Quantity, ScheduleDate = myDate, Type = 'Revenue'));
  
    }//end of inner IF

else{
listOLIS.add(new OpportunityLineItemSchedule(OpportunityLineItemId = oli.Id, Revenue = oli.Discounted_Price__c*oli.Quantity*oli.Duration__c, ScheduleDate = myDate, Type = 'Revenue'));

}//end of else

}//end of Up Front IF 


insert listOLIS;

}

}//end of isInsert

}//end of trigger
Jim RaeJim Rae
I would say that you would know best exactly what business functionality you expect your trigger to do. But, I would say you will need a Testmethod that creates an account and Opportunity, and then adds an Opportunity Line item ( actually looks like you need 2, one for each product you are interacting with). Best practice would say you should also create the pricebooks, products and PricebookEntries as well. I also notice you have several IDs hardcoded in your trigger, this is not a good idea, as they may be different between Sandbox and Production. You should query for those IDs based on something like the name, this will definitely be necesary if you are creating your own test data. This is a great overview document that describes the basic process and requirements around Testmethods, that is where you should start. https://developer.salesforce.com/page/An_Introduction_to_Apex_Code_Test_Methods
travis.truetttravis.truett
As for the IDs that I have hardcoded into my trigger, those are two pricebook entries for which we have a special case...is there a better field within OpportunityLineItem that I can call to single out those two pricebook entries? 
Jim RaeJim Rae
So you can still use your logic, just don't hardcode the IDs, look them up instead:
 
ID OnboardingPBE = [select id from PricebookEntry where product2.name='Onboarding' LIMIT 1].id;
ID TrainingPBE = [select id from PricebookEntry where product2.name='Training' LIMIT 1].id;

if(oli.PricebookEntryId ==OnboardingPBE || oli.PricebookEntryId ==TrainingPBE){//These are the Pricebook Entry IDs of Onboarding and Training, our two services.

 
travis.truetttravis.truett
we have a field in product called product family, and both of these entries belong to the service category. Belonging to the service product family is actually the condition that needs to be met to run this code. Can I say where ProductFamily = 'Services' in this select statement? Or is there a way I can get it to pull from there? If not, I can always just edit this code every time we add a new service, but it would be convenient to have a catch all.

Thanks so much for your help.
Jim RaeJim Rae
You could do that as well, at least for the "or" part of your code. If you need to treat each of the products differently, you would still need to identify each separately.
travis.truetttravis.truett
I just need to treat the two different product families differently. How could I select from one of the families?
Jim RaeJim Rae
Use product2.family.