+ Start a Discussion
salesforce_hoonigansalesforce_hoonigan 

Help with APEX Code

Hello Experts,

I am an Administrator and has very minimal and basic knowledge with Apex. I am having difficulties deploying the Apex Class and triggers into production. Basically, what I wanted to do is to count the number of Activity Records created by a specific User Profile and attached to a Lead and then populate the custom field on Leads called Activity_Count__c. When I test the code on Sandbox, it is working as intended, but when I try to deploy it in Production, I'm getting two errors and need assistance on fixing that.

Here are the errors:

► TaskUpdateLead, Details: Test coverage of selected Apex Trigger is 0%, at least 1% test coverage is required
► TestLeadActivityCount.testCountTask(), Details: System.QueryException: List has more than 1 row for assignment to SObject Class.TestLeadActivityCount.testCountTask: line 16, column 1

Below are the codes:

CLASS:
public with sharing class LeadActivityCount {
 
    public static Boolean didRun = false;
    public static String ledsPrefix =  Lead.sObjectType.getDescribe().getKeyPrefix();
 
    /*
    * Takes a set of lead IDs, queries those leads, and updates the activity count if appropriate
    */
    public static void updateLeadCounts(Set<ID> ledsIds) {
 
        if (didRun == false) { //We only want this operation to run once per transaction.
            didRun = true;
 
            //Query all the leads, including the tasks child relationships
            List<Lead> leds = [SELECT ID, Activity_Count__c, (SELECT ID FROM Tasks where CreatedBy.ProfileId='00ed0000000TZr6'), (SELECT ID FROM Events where CreatedBy.ProfileId='00ed0000000TZr6') FROM Lead WHERE ID IN :ledsIds];
            List<Lead> updateLeds = new List<Lead>();
 
            for (Lead l : leds) {
                Integer count = l.tasks.size() + l.events.size();
 
                if (l.Activity_Count__c != count) {
                    l.Activity_Count__c = count;
                    updateLeds.add(l); //we're only doing updates to leads that have changed...no need to modify the others
                }
            }
 
            //Update the appropriate leads
            try {
                update updateLeds;
            } catch (Exception e) {
                //This is controversial. Anything could happen when updating the opportunity..validation rule, security, etc. The key is we don't
                //want the event update to fail...so we put a try catch around the opp update to make sure we don't stop that from happening.
            }
        }
    }
}

TEST CLASS:
@IsTest
private class TestLeadActivityCount {

  public static Boolean didRun = false;
  public static String ledsPrefix =  Lead.sObjectType.getDescribe().getKeyPrefix();
   
    /*
    * Test method for this class and TaskUpdateLead and EventUpdateLead
    */
    public static testMethod void testCountTask() {
        //Setup

        Lead leds = new Lead(lastname='Test', email='1@2.com', company='Test');
        insert leds;

        User u = [select ProfileId from User where ProfileId ='00ed0000000TZr6'];
    
    System.runAs(u) {
        //Insert our first task
        Task t = new Task(subject='Test Activity', whoId = leds.id);
        insert t;
        
        //Verify count
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(1,leds.Activity_Count__c);

        //Disconnect task from the lead
        didRun = false; //Reset
        t.whoId = null;
        update t;
        //Verify count = 0
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(0,leds.Activity_Count__c);

        didRun = false; //Reset
        //Add an event
        Event e = new Event(subject='Test Event', whoId = leds.id, startDateTime = System.Now(), endDateTime = System.now());
        insert e;

        //Verify count = 1
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(1,leds.Activity_Count__c);

        //Relink the task to the lead
        didRun = false; //Reset
        t.whoId = leds.id;
        update t;

        //Verify count = 2
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(2,leds.Activity_Count__c);

        //Disconnect the event from the lead
        didRun = false; //Reset
        e.whoId = null;
        update e;

        //Verify count is back down to 1
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(1,leds.Activity_Count__c);

        //Delete the task
        didRun = false; //reset
        delete t;
        //Verify count is back down to 0
        leds = [SELECT ID, Activity_Count__c FROM Lead WHERE ID = :leds.id];
        System.assertEquals(0,leds.Activity_Count__c);
    }
   }
}

TRIGGER:
 
trigger TaskUpdateLead on Task (after delete, after insert, after undelete, after update) {

    Set<ID> ledsIds = new Set<ID>();
    //We only care about tasks linked to leads.
    String prefix =  LeadActivityCount.ledsPrefix;

    //Add any lead ids coming from the new data
    if (Trigger.new != null) {
        for (Task t : Trigger.new) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(prefix) ) {
                ledsIds.add(t.whoId);
            }
        }
    }

    //Also add any lead ids coming from the old data (deletes, moving an activity from one lead to another)
    if (Trigger.old != null) {
        for (Task t : Trigger.old) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(prefix) ) {
                ledsIds.add(t.whoId);
            }
        }
    }

    if (ledsIds.size() > 0)
        LeadActivityCount.updateLeadCounts(ledsIds);

}

Any assistance is greatly appreciated.

 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
@salesforce_hoonigan:

It is complaining that the query.,
User u = [select ProfileId from User where ProfileId ='00ed0000000TZr6'];

is returning more than one rows for which you can solve it by

User u = [select ProfileId from User where ProfileId ='00ed0000000TZr6' limit 1];

But, this is not the ideal way to do so., insteady you can create one test as in the link below:

https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_tools_runas.htm

In the testclasses, the idea is not to rely on the data that was in the current org at any time, instead create test data. 

I would recommend you to first have a quick fix by limiting rows, then modify it as per the standards :)

Cheers,
Hope it helps.,

Thanks,
balaji