0

I'm unable to cover the code coverage for catch block.Kindly help me to cover that code lines as well.

enter image description here

Apex Class:

public without sharing class ZTS_EU_Contact_populateCallDates
{
        Map <id, date> mapConIdDate = new Map<id, Date>();
        Map <ID, List<Attendee__C>> mapCallAttendees = new Map<ID, List<Attendee__C>>();
        Map <id, id> mapAttcon = new Map<id, id>();
        List<Contact> listCon = new List<Contact>();
        LIst <Attendee__C> listAttendee = new List<Attendee__C>();
        List <Attendee__C> listAllAttendee = new List<Attendee__C>();
    
        public void getLastCallDate(List<Call__C> triggerNew){

            for(CAll__C oCall: [SELECT id FROM CAll__C WHERE ID IN :TriggerNew])
            {
                mapCallAttendees.put(oCall.id,null);
            }

            for(Attendee__C oAtt : [SELECT ZTS_EU_call__C, id ,ZTS_EU_Contact__C FROM Attendee__C WHERE ZTS_EU_call__c in :TriggerNew])
            {
                listAttendee.add(oAtt);
                System.debug('OATT:;;;;'+oAtt);
                List <Attendee__c> newList = mapCallAttendees.get(oAtt.ZTS_EU_call__c);
                if(newList == null) newList = new List<Attendee__C>();
                newList.add(oAtt);
                mapCallAttendees.put(oAtt.ZTS_EU_call__C, newList);
                mapAttCon.put(oAtt.id, oAtt.ZTS_EU_Contact__C );
            }
            System.debug('listAttendee:;;;;'+listAttendee);
            if(listAttendee.size() >0){

                system.debug('mapCallAttendees ::::'+ mapCallAttendees.size());
                listAttendee = [SELECT ZTS_EU_Contact__c FROM Attendee__C WHERE ZTS_EU_Call__c IN :mapCallAttendees.keyset()];
                LIst <id> listConID = new List<id>();
                for(Attendee__c oAtt: listAttendee)
                {
                    listConID.add(OAtt.ZTS_EU_Contact__c);
                }

                listAllAttendee = [SELECT id,ZTS_EU_Contact__c from Attendee__C where ZTS_EU_Contact__c IN : listConID];
                List<id> listAttID =  new List<id>();
                for(Attendee__C oAtt1: listAllAttendee)
                {
                    listAttID.add(oAtt1.id);
                    mapAttCon.put(oAtt1.id, oAtt1.ZTS_EU_Contact__C );
                }
                system.debug('mapAttCon ::::'+ mapAttCon.size());

                //Updated Query to filter only Submitted & Planned Calls - NoorbashaSheik Chanbasha - 11/18/2021 - [SC-008964]
                List <AggregateResult> results = [SELECT ZTS_EU_Contact__c con,Max(ZTS_EU_call__r.ZTS_EU_Start_Date_Time__c) date from Attendee__c WHERE ID IN: listAttID AND (ZTS_EU_call__r.ZTS_EU_Status__c= 'Submitted' OR ZTS_EU_call__r.ZTS_EU_Status__c='Completed') Group BY ZTS_EU_Contact__c];
                for(AggregateResult ar: results)
                {
                    mapConIdDate.put(String.valueOf(ar.get('con')), Date.valueOF(ar.get('date')));                    
                }
                for(Call__c oCall: triggerNew)
                {
                    for(Attendee__c oAtt : mapCallAttendees.get(oCall.id))
                    {
                        Contact oCon = new Contact();
                        oCon.id = mapAttcon.get(oAtt.id);
                        system.debug('Before assigning call :::'+ oCall.ZTS_EU_Start_Date_Time__c);
                        system.debug('Before assigning :::'+ mapConIdDate.get(oCon.id));
                        if(oCall.ZTS_EU_Start_Date_Time__c > mapConIdDate.get(oCon.id))
                        {
                            system.debug('Before assigning :::'+ mapConIdDate.get(oCon.id));
                            system.debug('call start date :::'+ oCall.ZTS_EU_Start_Date_Time__c);
                            mapConIdDate.put(oCon.ID, Date.valueOf(oCall.ZTS_EU_Start_Date_Time__c));
                            system.debug('After assigning :::'+ mapConIdDate.get(oCon.id));
                        }
                        
                    }
                }
                for(ID conId : mapConIdDate.keyset())
                {
                    system.debug('conId :::'+ conId);
                    Contact oCon = new Contact(id = conId );
                    system.debug('final date :::'+ mapConIDDate.get(conId ));
                    oCon.ZTS_EU_Last_call_Date__c = mapConIDDate.get(conId );
                    system.debug('Print Last date :::'+ oCon.ZTS_EU_Last_call_Date__c);
                    listCon.add(oCon);
                } 
                try {
                    update(listCon);
                } catch(DmlException dex) {
                    String errorMessages = '';
                    for (Integer i = 0; i < dex.getNumDml(); i++) {
                        System.debug('ZTS_EU_Contact_populateCallDates.getLastCallDate ');
                        System.debug('DML Message: ' + dex.getDmlMessage(i));
                        errorMessages += dex.getDmlMessage(i) + '\n';
                    }
                    errorMessages.removeEnd('\n');
                    ZTS_EU_Logger.notify = true;
                    ZTS_EU_Logger.error(errorMessages,null, 'ZTS_EU_Contact_populateCallDates.getLastCallDate Contact DML error');
                }

        }
    }
}

Test Class :

@isTest
public class ZTS_EU_Contact_populateCallDatesTest 
{
    static testMethod void validate_ZTS_EU_Contact_populateCallDates() {
        ZTS_DataUtilityTest.createPrimaryContactInactiveProfileCustomSetting(); 
        User usr = new User();
        usr = ZTS_EU_DataUtilityTest.createUserWithProfile('System Administrator', false);
        usr.FirstName = 'davidsUser';
        usr.zts_eu_market__c = 'United Kingdom';
        insert usr;

        System.runAs(usr)
        {
            Map <id, date> mapConIdDate = new Map<id, Date>();
            Map <ID, List<Attendee__C>> mapCallAttendees = new Map<ID, List<Attendee__C>>();
            Map <id, id> mapAttcon = new Map<id, id>();
            List<Contact> listCon = new List<Contact>();
            LIst <Attendee__C> listAttendee = new List<Attendee__C>();
            List <Attendee__C> listAllAttendee = new List<Attendee__C>();

            ZTS_EU_Contact_populateCallDates popdates= new ZTS_EU_Contact_populateCallDates();
            List<Contact> contactList=ZTS_EU_DataUtilityTest1.createContactRecord(1);
            contactList[0].ZTS_EU_Market__c = 'United Kingdom';
            insert contactList;
            test.startTest();
            List<Call__c> callList = ZTS_EU_DataUtilityTest1.createCallRecord(1);
            insert callList;

            List<Attendee__c> attenList=new List<Attendee__c>();
            //List<Attendee__c> attenList=ZTS_EU_DataUtilityTest1.createAttendee(1);
            //insert attenList;
            Attendee__c attendee = new Attendee__c();
            attendee.ZTS_EU_Contact__c = contactList[0].Id;
            attendee.ZTS_EU_call__c = callList[0].Id;
            attenList.add(attendee);
            insert attenList;
            //mapCallAttendees.put(callList[0].id,attenList);
            popdates.getLastCAllDate(callList);
            test.stopTest();
        }
    }
}
1
  • 3
    Did you try some basic checks where DML can fail such as 1. inconsistent data which will lead to failure of Business Logic (maybe the validations) and hence the DML 2. Missing Mandatory field in the test data 3. Or something particular scenario for your business logic, which you think can lead to DML exception in real world.
    – user43598
    Commented Jan 12, 2022 at 10:40

2 Answers 2

2

The general solution for coercing an exception is via dependency injection of a mock object that replaces a runtime object where the mock object:

  • sets a field value such that the DML will fail
  • throws an exception when the mock object is invoked

This requires restructuring your code into Separation of Concerns patterns. A sophisticated one is the fflib pattern along with apexmocks but others exist as well.

A way to wrap your head around this is to use the HttpCalloutMock as an example. In a testmethod, SFDC will invoke your mock callout responder.

What you'll need is to restructure your code to use a ContactUpdater object that you can mock at testmethod time, injecting it into the code-under-test. Such mock ContactUpdater object could null out the Contact.LastName thus coercing a DML exception (as LastName is a schema-required field)

0

We can use validation rules here. Check Contact validation rules which can fire at contact update. Create contact with those values which will be used to fire validation rule. So you can get DML exception here.

if you don't have any validation rules to fire at Contact update. try to move these exception block code to separate method in the class and use it test class. I know it is not a good practice but this is the way to get good test class coverage.

try{
// use any DML and it should fail here
}catch(DMLException ex) {
 // call the new method which will have exception code.
}
1
  • Using existing validation rules would be valid, I think that adding an arbitrary validation rule is not the way to go here, and it wouldn't cover the real-world scenario that it seems OP is trying to cover. Not to mention it could create unforseen consequences in business processes. You may want to bring your "I know it is not a good practice" disclaimer up to the beginning of that paragraph. Commented Jan 12, 2022 at 12:17

You must log in to answer this question.

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