1

I am working on an Org with some old code that is beyond my admin / learing Apex ability to fix. This trigger is throwing errors for two many future calls and it no long serves any purpose in our Org. My first thought was to deactivate it and or comment it out in the Sandbox and deploy a change set. The deployment failed because code coverage is only at 72%. I am assuming that if I can fix the code coverage rather than just turn off the trigger and handler then I can deploy? The trigger has 51% code coverage and the handler has 0%. Trigger

trigger ContactTrigger on Contact (before insert, after insert, after update, before update) {
//
    //Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Trigger to update the Geolocation fields on Influencer(Contact) object
//
    if(Trigger.isInsert && Trigger.isBefore){
       if(System.label.Disable_Influencer_Owner_Change == 'false'){
             list<contact> contlist = trigger.new;
             for(contact cont: contlist){
                 cont.InfluencerOwner__c = cont.ownerid;
                 cont.ownerid = System.label.NewOwnerId;
             }
       }
    }

    if(Trigger.isUpdate && Trigger.isBefore){
     System.debug('####### Before update cont.influencerOwner__c ');

       if(System.label.Disable_Influencer_Owner_Change == 'false'){
             list<contact> oldcontlist = trigger.old;
             list<contact> newcontlist = trigger.new;
             System.debug('####### Before update '+oldcontlist.size());             
             for(contact cont: newcontlist){
                 contact oldContact = Trigger.oldMap.get(cont.Id);
                 /*
                 if (cont.InfluencerOwner__c != null && cont.ownerid != cont.influencerOwner__c) {
                     cont.InfluencerOwner__c = cont.ownerid;
                     cont.ownerid = System.label.NewOwnerId;
                 }*/
                  if(cont.influencerOwner__c == null){
                     System.debug('####### cont.influencerOwner__c '+System.label.NewOwnerId);
                     cont.InfluencerOwner__c = cont.ownerid;
                     cont.ownerid = System.label.NewOwnerId;                 
                 }
             }
       }

    }

    if ( Trigger.isInsert && Trigger.isAfter ) {
        //ContactTriggerHandler.afterInsert( Trigger.new );
    }
    else if ( Trigger.isUpdate && Trigger.isAfter ) {
        //ContactTriggerHandler.afterUpdate( Trigger.new, Trigger.oldMap );
    }
    else if ( Trigger.isUpdate && Trigger.isBefore ) {
        //ContactTriggerHandler.beforeUpdate( Trigger.new, Trigger.oldMap );
    }

    if(Trigger.isAfter){
        if(checkRecursive.runOnce())
        {
            System.debug('######## Contact trigger Called ');
            System.debug('########System.Label.Disable_Interface_Flow '+System.Label.Disable_Interface_Flow);            
            if('False' == System.Label.Disable_Interface_Flow){
                 System.debug('######## Called syncCustomer code');
                SendAccountUsingRestApi.syncCustomer();
            }
            if(Trigger.isUpdate){
                if('False' == System.Label.DISABLE_PARDOT_ASSIGNMENT_CALL){
                    CustomPARDOT.assignProspectsByContact(Trigger.new);
                }
            }
         if('false' == System.Label.DISABLE_RELATIONSHIP_OWNER_SHARING){
           InfluencerSharingWithRelationshipOwner.sharewithRelationshipOwner(Trigger.new);
         }
         System.debug('::CONTACT SENT TO PARDOT::');

        }
    }
}

Handler

public without sharing class ContactTriggerHandler {
//

//Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Trigger Handler to update the Geolaction fields on Influencer(Contact) object
//
    //Method to get all the new inserted records
    public static void afterInsert( List<Contact> newContactList ) {
        addToGeocodeServiceBatch( newContactList );
    }

    //Method to get all the updated records where Mailing Address has been changed
    public static void afterUpdate( List<Contact> newContactList, Map<Id, Contact> oldContactMap ) {
        List<Contact> conToUpdate = new List<Contact>();
        for ( Contact con : newContactList ) {
            if ( con.MailingStreet != oldContactMap.get(con.Id).MailingStreet
            || con.MailingCity != oldContactMap.get(con.Id).MailingCity
            || con.MailingState != oldContactMap.get(con.Id).MailingState
            || con.MailingPostalCode != oldContactMap.get(con.Id).MailingPostalCode
            || con.MailingCountry != oldContactMap.get(con.Id).MailingCountry ) {

                conToUpdate.add( con );

            }
        }
        if( conToUpdate.size() > 0 ) {
            addToGeocodeServiceBatch( conToUpdate );
        }
    }

    //Method to nullify Latitude and Longitude on Address change 
    public static void beforeUpdate( List<Contact> newContactList, Map<Id, Contact> oldContactMap ) {
        for ( Contact con : newContactList ) {
            if ( con.MailingStreet != oldContactMap.get(con.Id).MailingStreet
            || con.MailingCity != oldContactMap.get(con.Id).MailingCity
            || con.MailingState != oldContactMap.get(con.Id).MailingState
            || con.MailingPostalCode != oldContactMap.get(con.Id).MailingPostalCode
            || con.MailingCountry != oldContactMap.get(con.Id).MailingCountry ) {

                con.Location__latitude__s = null;
                con.Location__longitude__s = null;

            }
        }
    }

    //Method to call the geocode method to update the geolocation fields on Influencer(Contact) object
    public static void addToGeocodeServiceBatch( List<Contact> newContactList ){
        GeocodeService.geocode(
            newContactList
            ,'Address__c'
            ,'Location__latitude__s'
            ,'Location__longitude__s'
            ,true //true means run @future
        );
    }

}

Test Class

@isTest
private class TestContactTriggerHandler {
//

//Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Test Case for Contact Trigger Handler 
//

    //Method to Test the autofill of Location field on Influencer(Contact) record
    static testMethod void TestPopulateCategories() {
        List<Contact> con = new List<Contact>();

        for ( Integer i = 0; i < 2; i++ ) {
            con.add( UtilTest.createInfluencer( i, false ) );
        }


        Test.startTest();

        //Testing insert Trigger
        insert con;
        con = [SELECT Id, Name, MailingStreet, MailingCity, MailingState, MailingCountry, MailingPostalCode FROM Contact];
        System.assert( con[0].Name.contains( 'First' ), 'Insert Assert Failed' + con[0].Name );

        //Testing Update trigger
        con[0].MailingStreet = 'B-16';
        update con;
        con = [SELECT Id, Name, MailingStreet, Location__latitude__s  FROM Contact];
        //Testing after Update Trigger
        System.assert( con[0].MailingStreet.contains( 'B-16' ), 'Update1 Assert Failed' + con[0].MailingStreet );
        //Testing before Update Trigger
        System.assertEquals( null, con[0].Location__latitude__s , 'Update2 Assert Failed' );

        Test.stopTest();
    }   

}

  • Comment the 3 IF - ELSE statements above the ContactTriggerHandler method calls in your trigger. Deploy your trigger only. Do not deploy the class ContactTriggerHandler since you have already commented the references to it. Check and note the test classes for the following classes : SendAccountUsingRestApi, CustomPARDOT and InfluencerSharingWithRelationshipOwner. When validating your change set, select 'Run Specified Tests' and provide the names of the 3 test classes you noted above like : TestClass1,TestClass2,TestClass3 . See if it still fails due to coverage issue. – N.. Jun 28 '18 at 13:57
  • 3
    Might be a good idea to remove the personal information from the comments in the code – Folkert Jun 28 '18 at 14:45
2

ContactTriggerHandler never gets called because it's commented out in the trigger so it never gets tested, if you want to comment out all the code just wrap your code in /**/, that's if you truly don't want any of this logic anymore. Also with that being said, before I remove code from an org ill launch it commented out and leave it for a week, if no one complains about it ill remove it the following week.. Personal preference

This is my preferred way to delete from production http://www.salesforceben.com/way-to-delete-apex-classes-from-production/

trigger ContactTrigger on Contact (before insert, after insert, after update, before update) {
//
//Author       :   Amit SanWariya(Appirio)
//Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Trigger to update the Geolocation fields on Influencer(Contact) object
//
    /*if(Trigger.isInsert && Trigger.isBefore){
       if(System.label.Disable_Influencer_Owner_Change == 'false'){
             list<contact> contlist = trigger.new;
             for(contact cont: contlist){
                 cont.InfluencerOwner__c = cont.ownerid;
                 cont.ownerid = System.label.NewOwnerId;
             }
       }
    }

    if(Trigger.isUpdate && Trigger.isBefore){
     System.debug('####### Before update cont.influencerOwner__c ');

       if(System.label.Disable_Influencer_Owner_Change == 'false'){
             list<contact> oldcontlist = trigger.old;
             list<contact> newcontlist = trigger.new;
             System.debug('####### Before update '+oldcontlist.size());             
             for(contact cont: newcontlist){
                 contact oldContact = Trigger.oldMap.get(cont.Id);

                 if (cont.InfluencerOwner__c != null && cont.ownerid != cont.influencerOwner__c) {
                     cont.InfluencerOwner__c = cont.ownerid;
                     cont.ownerid = System.label.NewOwnerId;
                 }
                  if(cont.influencerOwner__c == null){
                     System.debug('####### cont.influencerOwner__c '+System.label.NewOwnerId);
                     cont.InfluencerOwner__c = cont.ownerid;
                     cont.ownerid = System.label.NewOwnerId;                 
                 }
             }
       }

    }

    if ( Trigger.isInsert && Trigger.isAfter ) {
        ContactTriggerHandler.afterInsert( Trigger.new );
    }
    else if ( Trigger.isUpdate && Trigger.isAfter ) {
        ContactTriggerHandler.afterUpdate( Trigger.new, Trigger.oldMap );
    }
    else if ( Trigger.isUpdate && Trigger.isBefore ) {
        ContactTriggerHandler.beforeUpdate( Trigger.new, Trigger.oldMap );
    }

    if(Trigger.isAfter){
        if(checkRecursive.runOnce())
        {
            System.debug('######## Contact trigger Called ');
            System.debug('########System.Label.Disable_Interface_Flow '+System.Label.Disable_Interface_Flow);            
            if('False' == System.Label.Disable_Interface_Flow){
                 System.debug('######## Called syncCustomer code');
                SendAccountUsingRestApi.syncCustomer();
            }
            if(Trigger.isUpdate){
                if('False' == System.Label.DISABLE_PARDOT_ASSIGNMENT_CALL){
                    CustomPARDOT.assignProspectsByContact(Trigger.new);
                }
            }
         if('false' == System.Label.DISABLE_RELATIONSHIP_OWNER_SHARING){
           InfluencerSharingWithRelationshipOwner.sharewithRelationshipOwner(Trigger.new);
         }
         System.debug('::CONTACT SENT TO PARDOT::');

        }
    }*/
}




public without sharing class ContactTriggerHandler {
//
//Author       :   Amit SanWariya(Appirio)
//Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Trigger Handler to update the Geolaction fields on Influencer(Contact) object
//
    //Method to get all the new inserted records
   /* public static void afterInsert( List<Contact> newContactList ) {
        addToGeocodeServiceBatch( newContactList );
    }

    //Method to get all the updated records where Mailing Address has been changed
    public static void afterUpdate( List<Contact> newContactList, Map<Id, Contact> oldContactMap ) {
        List<Contact> conToUpdate = new List<Contact>();
        for ( Contact con : newContactList ) {
            if ( con.MailingStreet != oldContactMap.get(con.Id).MailingStreet
            || con.MailingCity != oldContactMap.get(con.Id).MailingCity
            || con.MailingState != oldContactMap.get(con.Id).MailingState
            || con.MailingPostalCode != oldContactMap.get(con.Id).MailingPostalCode
            || con.MailingCountry != oldContactMap.get(con.Id).MailingCountry ) {

                conToUpdate.add( con );

            }
        }
        if( conToUpdate.size() > 0 ) {
            addToGeocodeServiceBatch( conToUpdate );
        }
    }

    //Method to nullify Latitude and Longitude on Address change 
    public static void beforeUpdate( List<Contact> newContactList, Map<Id, Contact> oldContactMap ) {
        for ( Contact con : newContactList ) {
            if ( con.MailingStreet != oldContactMap.get(con.Id).MailingStreet
            || con.MailingCity != oldContactMap.get(con.Id).MailingCity
            || con.MailingState != oldContactMap.get(con.Id).MailingState
            || con.MailingPostalCode != oldContactMap.get(con.Id).MailingPostalCode
            || con.MailingCountry != oldContactMap.get(con.Id).MailingCountry ) {

                con.Location__latitude__s = null;
                con.Location__longitude__s = null;

            }
        }
    }

    //Method to call the geocode method to update the geolocation fields on Influencer(Contact) object
    public static void addToGeocodeServiceBatch( List<Contact> newContactList ){
        GeocodeService.geocode(
            newContactList
            ,'Address__c'
            ,'Location__latitude__s'
            ,'Location__longitude__s'
            ,true //true means run @future
        );
    }*/
}


@isTest
private class TestContactTriggerHandler {
//
//Author       :   Amit SanWariya(Appirio)
//Created Date :   15 Feb' 2016
//Task         :   T-476163
//Description  :   Test Case for Contact Trigger Handler 
//

    //Method to Test the autofill of Location field on Influencer(Contact) record
    /*static testMethod void TestPopulateCategories() {
        List<Contact> con = new List<Contact>();

        for ( Integer i = 0; i < 2; i++ ) {
            con.add( UtilTest.createInfluencer( i, false ) );
        }


        Test.startTest();

        //Testing insert Trigger
        insert con;
        con = [SELECT Id, Name, MailingStreet, MailingCity, MailingState, MailingCountry, MailingPostalCode FROM Contact];
        System.assert( con[0].Name.contains( 'First' ), 'Insert Assert Failed' + con[0].Name );

        //Testing Update trigger
        con[0].MailingStreet = 'B-16';
        update con;
        con = [SELECT Id, Name, MailingStreet, Location__latitude__s  FROM Contact];
        //Testing after Update Trigger
        System.assert( con[0].MailingStreet.contains( 'B-16' ), 'Update1 Assert Failed' + con[0].MailingStreet );
        //Testing before Update Trigger
        System.assertEquals( null, con[0].Location__latitude__s , 'Update2 Assert Failed' );

        Test.stopTest();
    } */  
}
  • Thank you for sharing that tool with me. Is there anything different that needs to be done for a trigger vs a class? – Brooks Johnson Jun 28 '18 at 17:41
1

So here you have a TriggerHandler that is filled with static methods. This is a super simple fix. Create you some test data in a test class method annotated with @TestSetup and use that data to feed the parameters in this trigger handler by calling the handler as you would if you were triggering this from your trigger. Then all you will need to do is System.assertNotEquals(....) OR System.assertEquals(.....) whatever transformation was done in the appropriate method in your handler. This is simple test coverage that you can do. For some how-to if your apex development abilities are limited I would however suggest to spend a couple hours working with Salesforce Trailhead modules so that you can get a little understanding of what you are actually doing. There are many modules that can fit anything you wish to learn the basics for.

Test Coverage Module

  • 1
    Thanks, Ronnie, just completed Apex Unit Tests on Trailhead this week. Definitely a module worth repeating though. – Brooks Johnson Jun 29 '18 at 9:52
0

Your 0% in TriggerHandler coverage is because its methods are commented out from Trigger. You should either -preferably- write real tests for this class or just call test in a test method and then call System.assert(true). If you remove the comments, the code coverage will increase but someone commented them out for a reason.

0

I'm going through this right now on one of my sandboxes. Just a lot of old, expensive code that isn't used anymore, but still runs.

It might not be best practice, but I've been removing the bodies of the classes, by commenting them out. The whole thing, all the methods & signatures, everything. Not just the method calls. If theres no body, theres nothing to test or run, but everything that links to it will break in compile time, giving me a change to find and fix it, before I remove it.

You could try adding more code coverage, but honestly, if this code isn't in use, it might be best to remove it. Plus, if it doesn't run due to excessive limits, you'll have to refactor the code in order to have it run at all, before you can even test it. Not worth it.

The actual method of deleting a class (from production) is a pain. Heres an extensive question on method to do just that.

  • It seems like no matter what I do I am not able to comment it out. It passes the tests. But I still get a code coverage error. I am little lost about how to increase code coverage if I can't turn off any of it. – Brooks Johnson Jun 28 '18 at 17:36
  • Is it a 0% or a 75% error? Triggers need at least some amount of test coverage, while classes need 75% coverage. You should leave at least a DML operation in the test, but remove everything else. Youll at least call the trigger in a text context - it should be "covered" even tho its not doing anything – battery.cord Jun 28 '18 at 17:45
  • I tried and failed for 70% code coverage – Brooks Johnson Jun 28 '18 at 20:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.