You need to sign in to do that
Don't have an account?
Robert Haines
I am totally stuck, cant' see to get code coverage for this Apex trigger...
This trigger is designed to count activities on a lead, like # of calls, # of emails, etc. The code works well, but I can't for the life of me seem to be able to create a test class that gets sufficient code coverage. I get like 9% code coverage by creating a lead and creating a task in my test code. PLEASE SHOW ME HOW IT'S DONE if you would, please.
trigger FS_CountActivitiesOL on Lead (before update)
{
for(Lead lead : trigger.new)
{
id thisLeadID = lead.id;
List<Task> tasklist = [SELECT Type, CallDurationInSeconds, ActivityDate, FS_Connect__c From Task WHERE IsClosed = True AND whoid = :thisLeadID ORDER BY ActivityDate ASC];
if (tasklist.size() > 0) {
//Let's add up all the tasks
integer i = 0;
for(Task t : tasklist){
i++;
}
lead.FS_Activity_Count__c = i;
//Let's find the ACTIVITIES BEFORE FIRST CONNECT, EMAILS BEFORE FIRST CONNECT, CALLS BEFORE FIRST CONNECT, FIRST CONNECT DATE and FIRST CONNECT DURATION (IN SEC)
integer abfc = 0;
integer ebfc = 0;
integer cbfc = 0;
for(Task t : tasklist){
if (t.FS_Connect__c == FALSE) {
abfc++;
if (t.Type == 'Call') {
cbfc++;
}
ELSE IF (t.Type == 'Email') {
ebfc++;
}
}
Else {
if (t.Type == 'Call') {
cbfc++;
}
ELSE IF (t.Type == 'Email') {
ebfc++;
}
lead.FS_First_Connect_Date__c = t.ActivityDate;
lead.FS_First_Connect_Duration_Sec__c = t.CallDurationInSeconds;
abfc++;
break;
}
}
lead.FS_Activities_Before_First_Connect__c = abfc;
lead.FS_Calls_Before_First_Connect__c = cbfc;
lead.FS_Emails_Before_First_Connect__c = ebfc;
//Now let's get the FIST CALL DATE
for(Task t : tasklist){
if (t.Type == 'Call') {
lead.FS_First_Call_Date__c = t.ActivityDate;
break;
}
}
//Now let's get the FIRST EMAIL DATE
for(Task t : tasklist){
if (t.Type == 'Email') {
lead.FS_First_Email_Date__c = t.ActivityDate;
break;
}
}
//Now let's get the TOTAL # OF CALLS, TOTAL # OF EMAILS and TOTAL # OF CONNECTS
integer tncalls = 0;
integer tnemails = 0;
integer tnconns = 0;
for(Task t : tasklist){
IF (t.Type == 'Email') {
tnemails++;
}
ELSE IF (t.Type == 'Call') {
tncalls++;
}
IF (t.FS_Connect__c == TRUE) {
tnconns++;
}
}
lead.FS_Total_Number_of_Calls__c = tncalls;
lead.FS_Total_Number_of_Emails__c = tnemails;
lead.FS_Total_Number_of_Connects__c = tnconns;
}
}
}
trigger FS_CountActivitiesOL on Lead (before update)
{
for(Lead lead : trigger.new)
{
id thisLeadID = lead.id;
List<Task> tasklist = [SELECT Type, CallDurationInSeconds, ActivityDate, FS_Connect__c From Task WHERE IsClosed = True AND whoid = :thisLeadID ORDER BY ActivityDate ASC];
if (tasklist.size() > 0) {
//Let's add up all the tasks
integer i = 0;
for(Task t : tasklist){
i++;
}
lead.FS_Activity_Count__c = i;
//Let's find the ACTIVITIES BEFORE FIRST CONNECT, EMAILS BEFORE FIRST CONNECT, CALLS BEFORE FIRST CONNECT, FIRST CONNECT DATE and FIRST CONNECT DURATION (IN SEC)
integer abfc = 0;
integer ebfc = 0;
integer cbfc = 0;
for(Task t : tasklist){
if (t.FS_Connect__c == FALSE) {
abfc++;
if (t.Type == 'Call') {
cbfc++;
}
ELSE IF (t.Type == 'Email') {
ebfc++;
}
}
Else {
if (t.Type == 'Call') {
cbfc++;
}
ELSE IF (t.Type == 'Email') {
ebfc++;
}
lead.FS_First_Connect_Date__c = t.ActivityDate;
lead.FS_First_Connect_Duration_Sec__c = t.CallDurationInSeconds;
abfc++;
break;
}
}
lead.FS_Activities_Before_First_Connect__c = abfc;
lead.FS_Calls_Before_First_Connect__c = cbfc;
lead.FS_Emails_Before_First_Connect__c = ebfc;
//Now let's get the FIST CALL DATE
for(Task t : tasklist){
if (t.Type == 'Call') {
lead.FS_First_Call_Date__c = t.ActivityDate;
break;
}
}
//Now let's get the FIRST EMAIL DATE
for(Task t : tasklist){
if (t.Type == 'Email') {
lead.FS_First_Email_Date__c = t.ActivityDate;
break;
}
}
//Now let's get the TOTAL # OF CALLS, TOTAL # OF EMAILS and TOTAL # OF CONNECTS
integer tncalls = 0;
integer tnemails = 0;
integer tnconns = 0;
for(Task t : tasklist){
IF (t.Type == 'Email') {
tnemails++;
}
ELSE IF (t.Type == 'Call') {
tncalls++;
}
IF (t.FS_Connect__c == TRUE) {
tnconns++;
}
}
lead.FS_Total_Number_of_Calls__c = tncalls;
lead.FS_Total_Number_of_Emails__c = tnemails;
lead.FS_Total_Number_of_Connects__c = tnconns;
}
}
}
All Answers
@isTest(seeAllData=true)
private class TEST_FS_TRIGGERS
{
private static testMethod void myUnitTest()
{
// create a Lead
Lead lead=new Lead(
LastName='Doe',
FirstName='John',
Company='Test',
Status='Converted',
LeadSource='Other');
insert lead;
//create a Task
Task t = new Task();
t.OwnerId = UserInfo.getUserId();
t.Subject='No Subject';
t.Status='Not Started';
t.Priority='Normal';
t.type='Call';
t.whoId = lead.id ;
insert t;
Test.startTest();
lead.FS_Activity_Count__c=1.00;
update lead;
Test.stopTest();
System.AssertEquals('Call',t.type);
System.AssertEquals(1.00,lead.FS_Activity_Count__c);
}
}
Couple things I noticed, and maybe you can help address these too...
1) The t.Fs_Connect__c = true; part doesn't work because that field is a read-only formulat field, calculating it's value off another field.
2) When more thant 100 leads are updated at one time (using Mass Update feature in Leads view), I get this error...
Too many SOQL queries: 101
Error is in expression '{!step5}' in component <apex:commandButton> in page massupdatelead: Class.FSLeadUpdateClass.RunFSLeadUpdate: line 7, column 1
Trigger.FS_CountActivitiesOL: line 5, column 1
If it's at all possible to work around that (since it's feasible to update 200 leads at a time with the Mass Update feature), it would be great to figure this out. I tried creating a class with the @future tag, but any classes with that have to be void and cannot accept SObjects as parameters, so that seems like a dead end.
So, loop through all of the Leads that fired the trigger, and get their IDs. Then get the list of tasks for those leads and put in a map like map<LeadId,list<task>>
Then you can loop through all of the Leads again - and for each lead get the list of tasks just for that Lead and loop through those.
So - now - you have a filled in map. Now - remove the SOQL that was in your loop - and anywere you were looping through tasks - retrieve the mLeadIdTasks map and loop throug them.
So instead of this.....
You should have....
You'll need to finish up the code and maybe some cleanup - but that should give you the basic idea.
trigger FS_CountActivitiesOL on Lead (before update)
{
set<id> leadIds = new set<id>();
for(Lead lead : trigger.new)
{
leadIds.add(lead.id);
}
List<Task> tasks = [SELECT Type, CallDurationInSeconds, ActivityDate, FS_Connect__c From Task WHERE IsClosed = True AND whoid IN :leadIds ORDER BY ActivityDate ASC];
map<id,list<task>> mLeadIdTasks = new map<id,list<task>>();
for(task t : tasks)
{
List<task> iterTasks = new list<task>();
if(mLeadIdTasks.containsKey(t.whoid))
{
iterTasks = mLeadIdTasks.get(t.whoid);
}
iterTasks.add(t);
mLeadIdTasks.put(t.whoId,iterTasks);
}
if(mLeadIdTasks.containsKey(lead.id))
{
//this part is not working
//Error: Compile Error: Incompatible key type Schema.SObjectField for Map<Id,List<Task>> at line 25 column 8
}
}
How about the integer typo?
if(mLeadIdTasks.containsKey(lead.id))
{
//this part is not working
//Error: Compile Error: Incompatible key type Schema.SObjectField for Map<Id,List<Task>> at line 25 column 8
}
If that doesn't do it - paste back the code that you do have - (so I can see line #25).
But this code compiles on my system....
Error:Apex trigger FS_CountActivitiesOL caused an unexpected exception, contact your administrator: FS_CountActivitiesOL: execution of BeforeUpdate caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Task.WhoId: ()
Add back in WhoId ( I must have left it off for some reason)