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
Mark LiuMark Liu 

Deployment of a trigger failed due to error, “average test coverage for all Apex Classes and Triggers is 38%…"

Trigger and test class works in Sandbox with 100% code coverage (trigger code listed below)

I have checked the following:
1.My code coverage in Production is 98% and Sandbox is 94% according to Salesforce's "Developer Console"
2. I have turned off all Validation and Workflow rule in production to make sure it's not an issue with these rules before deployment (same result of 38% overall coverage where at least 75% is required)

I have reached with the conclusion that my trigger below is somehow breaking Apex Test Classes that are in place when I try to deploy, because along with the "38%" error message, it tells me that there are 5 other triggers (that are successfully deployed previously in production and is in production with 100% coverage) with 0% test coverage during deployment.

Please see my trigger below and please help resolve this mistery, thanks! 
(P.S. This trigger had worked before but I added MAP near the bottom of this new trigger hoping that this would resolve any issues when our users use CRM tools like Dataloader to mass update/insert old/new Contact records).
 
trigger primaryLiaisonCount2 on Contact(after update) {
  if(checkRecursive.runOnce())
  {
    List<Account> accList = new List<account>();
    List<Account> accListToUpdate = new List<account>();
    Set<Account> accSet = new Set<Account>();
    set<String> allAccIds = new Set<String>();    
    
    for (Contact c1: trigger.new){
        if (c1.Contact_ID_18_Characters__c != null){
        allAccIds.add(c1.AccountID);} }
   
   
    decimal amount1=[SELECT count() FROM Contact WHERE AccountID IN :allAccIds AND Primary_Liaison__c != null AND Marketing_Status__c != 'Gone From Company' LIMIT 25];
    LIST<Account> acc1=[SELECT ID FROM Account WHERE ID IN :allAccIds AND recordtypeID ='012000000000j8S' LIMIT 25];                             
       
    MAP<String, Account> firstMap = new MAP<String, Account>();
   for (Account acc2: acc1){
    firstMap.put(acc2.id, acc2);
   }
    
    for (Contact c1: trigger.new){
   Account acc3 = firstMap.get(c1.accountId);
   acc3.Primary_Liaisons__c = amount1;
   accList.add(acc3);                           
                        }
                                  
accSet.addall(accList);
accListToUpdate.addall(accSet);
Update accListToUpdate;
  }
  }
Best regards,
Mark
 
Shashikant SharmaShashikant Sharma
Hi,

Please see this : http://forceschool.blogspot.in/2011/06/testing-trigger-structure.html to see how test class for trigger is developed.

You need to create test data :

Account 
Contact
and then update the Contact

Let me know if you face issues in test class.

Although your trigger is not bulkified to may be you could see.http://forceschool.blogspot.in/search/label/Apex%20Triggers
Mark LiuMark Liu
Hey Shashikant,

Thanks for the prompt response. Sorry for not including my test class, please see it below, thank you.
 
@isTest
public class TestPrimaryLiaisonCount2{
    static testMethod void insertNewContact(){
    
    //NEW Account record
    Account acc = new Account();
    acc.recordtypeID = '012000000000j8S';
    acc.Name = 'Liu Inc';
    acc.Industry = 'Advertising';
    acc.NumberOfEmployees = 500;
    acc.Center__c = 'Full Service';
    acc.Move_out_of_view__c = False;
    insert acc;
    
    //NEW Contact record for 'ACC'
    Contact acdc = new Contact();
    acdc.FirstName = 'SUPERMAN';
    acdc.LastName = 'Kent';
    acdc.Primary_Liaison__c = 'Center';
    acdc.AccountID = acc.Id;
    acdc.Move_out_of_view__c = False;
    insert acdc;
    
    acdc.Primary_Liaison__c = null;
    update acdc;
    
    }
 }

 
Shashikant SharmaShashikant Sharma
There could be these reason for code coverage issue :

1. if(checkRecursive.runOnce()) stopping your test class to enter in trigger code - Could you post the code for it.
2. Contact_ID_18_Characters__c  is not populating , could you tell what is it , is it a formula field
3. Code coverage for this trigger is Ok but it is the over all organization code covergae is less which is stopping, do you have prior customization before this trigger. You could go to the trigger and see the code coverage for the trigger individually. You could also so the actual code coverage from developer console to check which code statements of this trigger are missing.

 
Mark LiuMark Liu
Hey Shashikant,

Thanks again.

1. Here's the test class for checkRecursive directly below.
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

2. Yes, it is a formula field that produces an 18-digit unique ID instead of only 15-digit ID. "c1.Contact_ID_18_Characters__c != null" can be switched to "c1.Id != null", it wouldn't make a difference here I don't think. The failure of deployment is after I add "MAP" into the trigger. Below is the code that's currently live and deployed in my production. I believe that I have bulkified the trigger before but not completely, that's why I was trying to add "MAP" to the trigger.
 
trigger primaryLiaisonCount2 on Contact(after update) {
	if(checkRecursive.runOnce())
	{
    List<Account> accList = new List<account>();
    List<Account> accListToUpdate = new List<account>();
    Set<Account> accSet = new Set<Account>();
    set<String> allAccIds = new Set<String>();    
    
    for (Contact c1: trigger.new){
        if (c1.Contact_ID_18_Characters__c != null){
        allAccIds.add(c1.AccountID);} }
   
   
    decimal amount1=[SELECT count() FROM Contact WHERE AccountID IN :allAccIds AND Primary_Liaison__c != null AND Marketing_Status__c != 'Gone From Company'];
    LIST<account> acc1=[SELECT ID FROM Account WHERE ID IN :allAccIds AND recordtypeID ='012000000000j8S'];                             
 
 for (Contact c1: trigger.new){
    
 for (Account acc2:acc1){
    acc2.Primary_Liaisons__c = amount1;
    accList.add(acc2);
                                
                        }}
                                  
accSet.addall(accList);
accListToUpdate.addall(accSet);
Update accListToUpdate;
	}
}
3. The overall code coverage for my production as I have explained in my initial post is still 98% (with each individual code at least over 75%). I don't know if this makes a difference, but in Sandbox, the overall code coverage is 94%. It really does look like the new trigger (with MAP added) somehow is breaking the existing test classes... making them fail... And because the test classes fail, that's why the overall code coverage went down from 98% to 38% (which then the computer fails my overall code coverage)... You think it's checkRecursive class that's breaking it? However, checkRecursive is included in the trigger directly above and was successfully deployed into production with no error...



Mark
 
Shashikant SharmaShashikant Sharma
Only think at this point I could think is that checkRecursive is called from account trigger or any other contact trigger abd it gets set to false.

To fix this you could try :
1. Change private to public for

public Class checkRecursive{
public static boolean run = true;

2. In test class add this checkRecursive.run = false :

acdc.Primary_Liaison__c = null;
checkRecursive.run = false;
update acdc;


You could see the coverage of trigger in developer console to see what code lines are not covered.