6

I'm pretty new to Apex and I'm trying to write a trigger that will update my LeadStatus field from 'Open-Not Contacted' to 'Open- Working' upon completion of sent email (logged in Activity History). Basically my Sales team sends out a mass email to their List views and after that first email is logged in Activity History, my LeadStatus field updates which in turns activates my process builder workflow.

I've done deep research and have finally put together a trigger and a test class, but I'm only getting 91% code coverage. The 9% that's failing is the update LeadStatus part which is the only reason I'm doing this.

Trigger

trigger EmailTask on Task (after insert) {
// set up lists
List<Lead> startProcess = new List<Lead>();
Map<Id, Task> taskMap = new Map<Id, Task>();

// go through the list of tasks that were inserted
for (Task t: Trigger.New)
{
  // add the Lead id (whoID) and their values to a map
  if (t.WhoId  != null)
    {
        taskMap.put(t.WhoId, t);
    }
}
// if the map is not empty
if (taskMap.size() > 0)
{
    // get all of the Leads related to the tasks
    startProcess = [SELECT Id, Status FROM Lead WHERE Id IN: taskMap.keySet()];
    // go through the list for each Lead
    for (Lead ld: startProcess)
    { if (ld.Status =='Open- Not Contacted')
        // set the new Lead status
      ld.Status = 'Open- Working';
    }
    update startProcess;

}
}

Test Class

@isTest(seealldata = false)

public class TestClassforTrigger {

static Lead createLead() { Lead ld = new Lead(); ld.LastName = 'Tulsani'; ld.Company ='ABC Corp'; ld.Status='Open- Not Contacted'; return ld; }

static Task createTask(Id ldId) {
    Task tk = new Task();
   tk.OwnerId= '005590879000Sx6';
    tk.Subject ='Call for test class';
    tk.WhoId = ldid;
    tk.Priority = 'Normal';
    return tk;
}

static testMethod void TestInsertTask() {
    Test.startTest();
    Lead createlead = createLead();
    insert createlead;
    Lead Getlead = [SELECT Status FROM Lead where ID = : createlead.id];
    Task tk = createTask(createlead.id);

    insert tk;
     Lead Getleadupdated = [SELECT Status FROM Lead where ID = : createlead.id];


    Test.stopTest();
    System.assertEquals('Open- Working', Getleadupdated.Status); 

}
}

3 Answers 3

12

The error is in your Status. In the trigger you've got:

if (l.Status =='Open- Not Contacted')

(note the n- N), and in your test class you create it as:

ld.Status='Open -Not Contacted';

(note the n -N). That misplaces whitespace is probably the reason why that line is not getting covered

Edit: Try to use constants for this kind of things. It will make your life easier.

5
  • 1
    This is a great example of why constants are useful. And also why moving code to an Apex Class is a good idea.
    – Adrian Larson
    Sep 27, 2016 at 14:00
  • I'm confused about constants... Should I change my 'ld' to just 'l'?
    – NikkiJ
    Sep 27, 2016 at 15:01
  • 2
    In your Apex class, define a constant with the new value. Reference that in your code and test class to keep it consistent. Something like public const string NewStatus = 'Open - Not Contacted';
    – Mike Chale
    Sep 27, 2016 at 15:03
  • There is also the issue of having "Open- Working" in the trigger and "Working- Contacted" in the test class.
    – Mike Chale
    Sep 27, 2016 at 15:09
  • I didn't end up establishing a constant (but I'll make sure to try and incorporate them from now on!) but after making a few edits thanks to your suggestion, I've got 100% code coverage. Thanks all for your help!
    – NikkiJ
    Sep 28, 2016 at 12:20
4

Among the other answers here you will still need to move this line to be after you insert your task.

Lead Getleadupdated = [SELECT Status FROM Lead where ID = : createlead.id];

Otherwise the value of your Status field will be what it was before the trigger was run.

Also please note that your Trigger will run for ANY Task that is created, whether it is an email or not. If your Sales Team only uses Tasks for emails then you have no problem, but if they use Tasks for other things this code will run every time.

2
  • 1
    While this will make the test fail it does not impact the code coverage issue OP is asking about.
    – Mike Chale
    Sep 27, 2016 at 15:10
  • 2
    @MikeChale Very true, and so my answer should not be accepted as THE answer, but I wanted to point this issue out to OP to help head off any further issues.
    – dBeltowski
    Sep 27, 2016 at 16:24
2

Note that this is not the correct answer. Leaving it here to notify others that you don't need to explicitly query the Id field, it will always be in the result set

you are inserting the Task without a Lead Id:

Lead Getlead = [SELECT Status FROM Lead where ID = : createlead.id];
Task tk = createTask(Getlead.id);

GetLead does not have an Id, because that was not queried in the SOQL query.

But you don't even need to requery the Lead. As soon as you insert the Lead, the createLead will contain the Id.

So do this:

Task tk = createTask(createLead.id);

And the last part of your code will be covered as well.

3
  • 1
    Are you sure id isn't added automatically? I just ran system.debug([select status from lead]); in the dev console and it returned id and status.
    – Mike Chale
    Sep 27, 2016 at 15:06
  • @MikeChale I thought that Salesforce on the backend always returned Id whether it was specified or not. Seems your test proves this out.
    – dBeltowski
    Sep 27, 2016 at 16:22
  • You are right Mike. My answer's not correct, indeed. Sep 28, 2016 at 9:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .