You need to sign in to do that
Don't have an account?
Unit Tests??? I am Lost...
Hello all-
i am trying to write my first Apex trigger and deploy it to a production org and am missing something. I have written the Trigger to do what I want but cannot see m to figure out how to write the unit tests for this and then deploy it to an org. I have gone over the documentation all day and still am hitting my head against a wall. Wondering if anyone would be so kind as to help me understand what the unit tests for a simple script like this would look like? I would be very greatful...or at least point me in the direction of a simple hello world example?
Code: trigger UpdateOpportunityLastActivityDate on Event (before insert, before update) { for (Event e : Trigger.new) { Opportunity[] opp = [select id from opportunity where id= :e.WhatId]; opp[0].Next_Activity_Date__c = e.ActivityDate; update opp; } }
Thanks in advance for any help/direction.
To unit test your Apex Trigger, you need to create an Apex Class containing test methods (using the TestMethod keyword) which exercise your trigger code. In this case, you would need test methods that insert and update Events.
When you deploy your Apex to production, the system will execute the test methods in your Apex class, and those test methods will cause your Apex trigger to be invoked, and that will count toward the minimum code coverage requirements.
But remember that the reason to create unit tests is not to get past our code coverage checker, but to actually make sure your code works as expected before exposing your end users to it. So when you write your Event test methods, you should think about different scenarios that would cause your trigger to fire and make sure you handle them.
For instance:
- Your code assumes that every Event.WhatId is an Opportunity Id. What if a user creates or updates an Event associated with an Account or other object?
- You perform a query and update for each Event in the loop. This works fine with a few Events, but what if someone batch-imports a large set of Events? Create a unit test that inserts or updates a large number of Events.
(You may want to use one loop to generate the set of Opportunity Ids, then execute a single query in which you retrieve all those Opportunities, and finally a single update statement to push your changes into the database in one transaction. This is far more efficient and will avoid the Apex governor limits.)
The developer.force.com wiki contains a number of excellent design patterns for addressing these scenarios, such as:
http://wiki.apexdevnet.com/index.php/BESTMassUpdateContactsOnAccount.apex
As you write more and more unit tests, you'll get better at identifying positive and negative scenarios, which will improve the quality of your code as you write it, and your confidence in it after you deploy it to production.
Jon
Message Edited by JonP on 01-28-2008 02:57 PM
Thanks for the help! I was able to get it up and running last night and deployed to a prod org via Eclipse.
Time for a beer...
Here's the code (note I modified the Hello World example to update a Lead vs. an Account):
helloWorldLeadTrigger
trigger helloWorldLeadTrigger on Lead (before update) {
MyHelloWorld.addHelloWorld(Trigger.new);
}
MyHelloWorld.cls
public class MyHelloWorld {
public static void addHelloWorld(Lead[] leads){
for (Lead aLead:leads){
if (aLead.Hello__c != 'World')
aLead.Hello__c = 'World';
}
}
static testMethod void myTest() {
System.Debug('');
System.Debug('Unit Test: Paul Hello World');
List<Lead> LeadToUpdate = new List<Lead>();
Lead myLead = new Lead();
myLead = [select id, Hello__c from Lead where lastname = 'Nugent'];
LeadToUpdate.add(myLead);
MyHelloWorld.addHelloWorld(LeadToUpdate);
}
}
Outputlog From Apex Code Test Runner:
helloWorldLeadTrigger:
Test coverage of selected Apex Trigger is 0%, at least 1% test coverage is required
General:
Test coverage of selected Apex Trigger is 60%, at least 75% test coverage is required
---
How do I bump up my %'s...especially on the trigger code itself?
Thanks for the help!
-P
MyHelloWorld.addHelloWorld(LeadToUpdate);
with:
update LeadToUpdate;
This will cause an update event, firing your trigger, and in turn calling your MyHelloWorld::addHelloWorld() method.
To increase your code coverage further, include a second lead in your update set, having Lead.Hello__c = 'World'. Then you'll have tested both branches of the if statement.
With these changes, your code coverage will look great, but are your tests actually accomplishing anything? This is just a Hello, World example, but consider going all the way and adding System.assert() statements to your test method.
For example, after the update statement in your test method, why not add:
for (Lead afterUpdateLead = [select id, Hello__c from Lead where lastName = 'Nugent']) {
System.assertEquals('World', afterUpdateLead.Hello__c);
}
Thanks a million for getting me over the hump! These nuggets of advice you provided are exactly what is missing from the documentaton. Obviously the 'Hello World' code is pretty worthless, but the overall concepts are now complete with your response, so I can't thank you enough.
Happy Coding,
-Paul
Do you have an idea to solve the following issue ?
I try to deploy my job but I get only 17 %test coverage.
trigger opportunity_after_insert on Opportunity (after insert) {
Opportunity[] opps=Trigger.new;
opportunity_clone.Opp_line_item_del(opps);
}
This trigger call opportunity_clone.Opp_line_item_del
but with my test method :
insert the opportunity then call my trigger ( when there is no opportunitylineitem ) and then it insert the opportunity line item .
So test covarage result is 17 %
static testmethod void opp_clone_oli_test(){
...
//Create opportunity
Opportunity o = new Opportunity (name='unitest',Pricebook2id=pb.id, Stagename='Initial Proposal Submitted', Closedate=Date.newInstance(2008,02,02));
insert o;
//Create opportunityline item
OpportunityLineItem[] Oli=new OpportunityLineItem[0];
oli.add(new OpportunityLineItem(Opportunityid=o.id,pricebookentryid=pbe.id,Quantity=1 ,UnitPrice=1000 , Frequency__c='Monthly',Billing_Term__c='12',Contract_Re_sign__c='No'));
oli.add(new OpportunityLineItem(Opportunityid=o.id,pricebookentryid=pbe.id,Quantity=1 ,UnitPrice=3000 , Frequency__c='Monthly',Billing_Term__c='12',Contract_Re_sign__c='No'));
insert oli;
opportunity opp_clone= o.clone(False) ;
List<OpportunityLineItem> updatedoli = o.OpportunityLineItems.deepclone(false);
for (OpportunityLineItem oli_C : updatedoli) {
oli_C.OpportunityId = opp_clone.Id;
updatedoli.add(oli_C);
}
update updatedoli ;
for (OpportunityLineItem ol : [SELECT Quote_Reference__c,ServiceDate,Provisioning_Type__c, Document_Type__c, Non_Verified_Contract__c FROM OpportunityLineItem WHERE Opportunityid = :opp_clone.id]) {
system.assertEquals(null,ol.Quote_Reference__c);
system.assertEquals(null,ol.ServiceDate);
system.assertEquals(null,ol.Provisioning_Type__c);
system.assertEquals('Order Form',ol.Document_Type__c);
system.assertEquals(False,ol.Non_Verified_Contract__c);
}
}
}
but rather just constructs an opp, with line items, then call the class itself, directly with the opp in an array
that should get your code coverage in the class to 100%
so, add (something like)
Message Edited by Ron Hess on 02-06-2008 11:31 PM
Thanks for those who have replied. I have found this very helpful. However I have run into another issue. I have a block of my code that is a big if/then statement to turn a Month value froma picklist into a integer so I can set a date object. I cannot reach 75% coverage of my code becuase the length of this if/then statement. Try as I may I cannot write a unit test for it. Wondering if anyone could point me in the right direction. Here is a snippet of the code that is preventing me from getting 75%.
Integer Month = 01;
... I iterate ofer the 12 months...
String YearStrng = JanSD.Inactivate_this_year__c;
Integer Year = Integer.valueOf(YearStrng);
Integer Day = 01;
Date deactivateDate = Date.newInstance(Year,Month,Day);