function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
John Neilan 18John Neilan 18 

Test Class not Covering Enough

I am trying to develop a test class to cover a trigger but I am only able to get to 64%. I'm not sure how to get the lines below covered. Can anyone advise?

Test Class:
Not covered - lines 13-16; lines 36-41; lines 47-56
@isTest
private class TestVIP_Types_Trigger {
    
    Private static testMethod void vipScenarioTests() {
        
Test.startTest();
        
        Account testAccount = new Account();
        	testAccount.Name = 'Test JN Account';
            testAccount.AccountSource = 'Networking';
		insert testAccount;
        
        Contact testContact = new Contact();
            testContact.LastName = 'LastTest';
            testContact.Phone = '5555555555';
            testContact.AccountId = testAccount.Id;
        insert testContact;

        Contact testContact2 = new Contact();
            testContact2.LastName = 'LastTest';
            testContact2.Phone = '5555555555';
            testContact2.AccountId = testAccount.Id;
        insert testContact2;
        
    	VIP_Type__c testVIP1 = new VIP_Type__c();
            testVIP1.Account__c = testAccount.Id;
            testVIP1.Contact__c = testContact.Id;
            testVIP1.VIP_Type__c = 'Ambassador';
        insert testVIP1;

        VIP_Type__c testVIP2 = new VIP_Type__c();
            testVIP2.Account__c = testAccount.Id;
            testVIP2.Contact__c = testContact.Id;
            testVIP2.VIP_Type__c = 'Influencer';
        insert testVIP2;

        Boolean errThrown = false;
        try{
        VIP_Type__c testVIP3 = new VIP_Type__c();
            testVIP3.Account__c = testAccount.Id;
            testVIP3.Contact__c = testContact.Id;
            testVIP3.VIP_Type__c = 'Ambassador';
        insert testVIP3;
        }catch(Exception e) {
            errThrown = true;
				Boolean expErr = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr, e.getMessage());
        }
        System.assertEquals(false,errThrown,'No exception was thrown');
        

        Boolean errThrown2 = false;
        try{
        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Ambassador';
        update testVIP2;
        }catch(Exception e) {
            errThrown2 = true;
				Boolean expErr2 = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr2, e.getMessage());
        }
        System.assertEquals(false,errThrown2,'No exception was thrown');

        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Celebrity';
        update testVIP2;

        VIP_Type__c testVIP1a = new VIP_Type__c();
            testVIP1a.Account__c = testAccount.Id;
            testVIP1a.Contact__c = testContact2.Id;
            testVIP1a.VIP_Type__c = 'Ambassador';
        insert testVIP1a;

        VIP_Type__c testVIP2a = new VIP_Type__c();
            testVIP2a.Account__c = testAccount.Id;
            testVIP2a.Contact__c = testContact2.Id;
            testVIP2a.VIP_Type__c = 'Celebrity';
        insert testVIP2a;

        delete testVIP1;
        delete testContact;
        delete testAccount;
Test.stopTest();
    }
}



Trigger:
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

 if(checkRecursive.runOnce())
    {
	Set<Id> acctIds = new Set<ID>();
	Set<Id> contIds = new Set<ID>();
//	  Set<String> vipTypes = new Set<String>();
	Map<VIP_Type__c, VIP_Type__c> contactTypeMap = new Map<VIP_Type__c, VIP_Type__c>();
	Map<Id, Set<String>> contactTypeMapDel = new Map<Id, Set<String>>();
    
// Get all the Account & Contact Ids in the Set 
	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);
            contactTypeMapDel.put(vip.Contact__c , new set<String>());
//            contactTypeMap.put(vip.Contact__c, vip.VIP_Type__c);
		}
	}
	else{

    	for(VIP_Type__c vip : Trigger.new) {
    		acctIds.add(vip.Account__c);
    		contIds.add(vip.Contact__c);
     	}
//	 }

	List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                            FROM VIP_Type__c
                            WHERE Contact__c = :contIds AND ID NOT IN:trigger.new];

//Check for VIP Types already entered for Contact
	Map<Id,set<string>> existingTypeMap = new Map<Id,set<string>>();
    
    for(VIP_Type__c vip: vipRecs) {
		set<string> existingTypes = new set<string>();
        if(existingTypeMap.containsKey(vip.Contact__c)){
            existingTypes = existingTypeMap.get(vip.Contact__c);
        }
        existingTypes.add(vip.VIP_Type__c);
        existingTypeMap.put(vip.Contact__c,existingTypes);
    }

	for (VIP_Type__c vip : trigger.new)
    {
        if (existingTypeMap.containsKey(vip.Contact__c)){
            if (existingTypeMap.get(vip.contact__c).contains(vip.VIP_Type__c)){
system.debug('@@@### - Check Map:  '+existingTypeMap.get(vip.contact__c));
system.debug('@@@### - Check VIP Type:  '+vip.VIP_Type__c);
                trigger.newMap.get(vip.Id).addError('This Type already exists for this Contact');
            }
            else
            {
                Set<string> existingTypes = existingTypeMap.get(vip.Contact__c);
                existingTypes.add(vip.VIP_Type__c);
                existingTypeMap.put(vip.Contact__c,existingTypes);
            }

        }
    } 
    }


// Query the Accounts
		List<Account> acct = new List<Account>();

// Use the VIP Types to get all the related Types for the Account 
			acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r ORDER BY VIP_Type__c) 
					FROM Account 
					WHERE Id in :acctIds]; 

// Iterate over each Account and VIP record 
			for(Account a : acct){ 
				a.VIP_Types__c = ''; 

				for(VIP_Type__c vip: a.VIP_Types__r){ 

					if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == ''){ // Check if the Type is already in the Account Field. if not add it otherwise skip 

					a.VIP_Types__c += vip.VIP_Type__c + '; '; 
					} 
				} 
			} 
// Update the Account 
		update acct; 
}
}

 
Best Answer chosen by John Neilan 18
John Neilan 18John Neilan 18
Thanks to you both! I know it's not a pretty test class, but the issue I ran into was around the checkRecursive line in my trigger. I removed that and got to 100%. Thanks!

All Answers

AbhishekAbhishek (Salesforce Developers) 
Try the suggestions and methods as mentioned in the below developer discussion,

https://salesforce.stackexchange.com/questions/244794/how-do-i-increase-my-code-coverage-or-why-cant-i-cover-these-lines


I hope you find the above information is helpful. If it does, please mark as Best Answer to help others too.

Thanks.
 
Andrew GAndrew G
not the sexist test class.  there are some issues.

but to answer your direct questions:

lines 13-16; - not sure, there is a delete happening. but i wonder if it has something to do with how you are handling the trigger contexts.  At this stage, i have no suggestion (second reading, it may do with the try..catch... in the middle)

lines 36-41;
you are trying to loop the array vipRecs  based on the SELECT statement, you will need to do a test class where a VIP records is NOT in the trigger.
I suspect that would be a bit of a re-write.

lines 47-56
since existingTypeMap appears to be populated duing the loop for vipRecs (above), solving 36-41 will probably solve this one.

Some tips:

Since your trigger has branching based on IF ... ELSE ... conditions, i would be looking to mulitple test methods, not trying to combine all into one.  It will give you coverage, but as a true test class, i would not rate it.

Since multiple test methods would (should) be required here, I would look at @testsetup.

Investigate what Test.teststart() and test.teststop() really do.  Your placement for your Test.teststart() makes no sense.

I suspect using @testsetup and proper placement of Test.teststart() will help with your coverage for the second two sections.

You have a try ... catch ... in the middle of your test class.  I understand you are doing this to cover the try ... catch... in the trigger, but its location  may also be causing issues.   move to separate test method ,

And asserts - good test classes will have asserts, and good asserts.  How else do you know your code is working and then not affected by other code that follows.



regards
Andrew

 
John Neilan 18John Neilan 18
Thanks to you both! I know it's not a pretty test class, but the issue I ran into was around the checkRecursive line in my trigger. I removed that and got to 100%. Thanks!
This was selected as the best answer