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
Tyler HarrisTyler Harris 

Batchable Apex Test Conflicting with Trigger

I've got a Batchable Apex test I've created that is throwing the following error:

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, setTrainingAccountId: execution of BeforeInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.setTrainingAccountId: line 55, column 1: []

I'm not sure why the Trigger is affecting my Test Class Execution. I haven't been able to pinpoint the exact issue. Any ideas?

Trigger
trigger setTrainingAccountId on Training__c (before insert, before update, after insert, after update, after delete, after undelete) {
    set<Id> setAttendees = new set<Id>();
    set<Id> setCourses = new set<Id>();

  set<Id> setUnknownAccounts = new set<Id>();
  
  for(Account a : [
    SELECT
      Id
    FROM
      Account
    WHERE
      Name LIKE '%End%User%'
      OR Name LIKe '%User%End'
  ]){
    setUnknownAccounts.add(a.Id);
  }
    
    if(trigger.isDelete){
        for(Training__c t : trigger.old){
            setAttendees.add(t.Attendee__c);
            setCourses.add(t.Course_or_Module__c);
        }
    }else{
        for(Training__c t : trigger.new){
            setAttendees.add(t.Attendee__c);
            setCourses.add(t.Course_or_Module__c);
        }
    }
    
    map<Id,Contact> mapContactAccount = new map<Id,Contact>([
    SELECT
            Id,
            AccountId
        FROM
            Contact
        WHERE
            Id IN : setAttendees
    ]);
    
    //map<Id, Course__c> mapCourses = new map<Id, Course__c>([SELECT Name, Duration_Hours__c FROM Course__c WHERE Id IN : setCourses]);
    map<Id,Course__c> mapCourses = new map<Id,Course__c>([
        SELECT
            Id,
            Name
        FROM
            Course__c
        WHERE
            Id IN : setCourses
    ]);
    
    //Jade Update : Account field update with current contact's account
    if(trigger.isBefore){
        for(Training__c t : trigger.new){
          if(setUnknownAccounts.contains(mapContactAccount.get(t.Attendee__c).AccountId)){
          t.addError('Assigning Training to a Contact associated with an Unknown End User Account is not allowed. Pleae assign the Contact to an existing Account or create a new one first.');
        }
            t.Account__c = mapContactAccount.get(t.Attendee__c).AccountId;
        }
    }
    /* if(trigger.isBefore){
        for(Training__c t : trigger.new){
            t.Account__c = mapContactAccount.get(t.Attendee__c).AccountId;
            if(t.Duration_Hours__c == null && trigger.isInsert){
                t.Duration_Hours__c = mapCourses.get(t.Course_or_Module__c).Duration_Hours__c;
            }
        }
    } */
    
    if(trigger.isAfter){
        set<Id> setAccounts = new set<Id>();
        
        if(trigger.isDelete){
            for(Training__c t : trigger.old){
                if(t.Course_or_Module__c != null){
                    if(
                        mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS Advanced Training')
                        || mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS PKI @ the Door Training')
                        || mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS Software Training')
                    ){
                        setAccounts.add(mapContactAccount.get(t.Attendee__c).AccountId);
                    }
                }
            }
        }else{
            for(Training__c t : trigger.new){
                if(t.Course_or_Module__c != null){
                    if(
                        mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS Advanced Training')
                        || mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS PKI @ the Door Training')
                        || mapCourses.get(t.Course_or_Module__c).Name.startsWithIgnoreCase('pivCLASS Software Training')
                    ){
                        setAccounts.add(mapContactAccount.get(t.Attendee__c).AccountId);
                    }
                }
            }
        }
        
        if(!setAccounts.isEmpty()){
            accountCertifications accountCertifications = new accountCertifications();
            accountCertifications.setAccountCertifications(setAccounts);
        }
    }
}

Test Class
@isTest
public class TestBatchUpdateTraining {

    Static testmethod void test(){
String Query = 'SELECT id,Training_Status__c,Expiry_Date__c FROM Training__c WHERE Expiry_Date__c < Today';
     

    
Training__c[] ml = new List<Training__c>();
        date mydate = date.parse('5/11/2014');
       for (Integer i=0;i<10;i++) {
           Training__c m = new Training__c(
               Course_or_Module__c= 'a0vn0000000EZsJ',
               Account__c = '001n0000005m8G0',
               Attendee__c ='003n0000006QMkP', //Learner
               Training_Status__c='Completed',
           		Expiry_Date__c = mydate);
           ml.add(m);
           System.debug(ml);
       }
    insert ml;
    
    Test.startTest();
    BatchUpdateTraining bit = new BatchUpdateTraining();
    Database.executeBatch(bit);
    Test.stopTest();
    
    Integer i = [SELECT COUNT() FROM Training__c WHERE Training_Status__c = 'Expired'];
    System.assertEquals(i, 0);
    }
}

Batch Update
global class BatchUpdateTraining implements Database.Batchable<sobject> {

     public String Query;

     public Database.QueryLocator start(Database.BatchableContext BC)  {  

        Query = 'SELECT id,Training_Status__c,Expiry_Date__c FROM Training__c WHERE Expiry_Date__c < Today';
		
        return Database.getQueryLocator(Query); 

    }

     public void execute(Database.BatchableContext BC, List<Training__c> scope) { 
        List<Training__c> tr = new List<Training__c>(); 
		System.debug(scope);
        for (Training__c ac : scope)  {
		ac.Training_Status__c = 'Expired';
        tr.add(ac);
        System.debug(tr.size());

       }

           update tr;
     }

 
    public void finish(Database.BatchableContext BC) {   
    AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,
      TotalJobItems, CreatedDate, CreatedBy.Email
      FROM AsyncApexJob WHERE Id =
      :BC.getJobId()];
	Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    List<String> toAddresses = new List<String> {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Training Expiration Job Processed ' + a.Status);
        mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems + ' batches with ' + a.NumberOfErrors + ' failures' + a.CreatedDate + 'Date Ran');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
   }

}

 
varun_vatsavarun_vatsa
Hi 

on line number 55 please replace the code by 

if(setUnknownAccounts!= null && mapContactAccount!=null && setUnknownAccounts.contains(mapContactAccount.get(t.Attendee__c).AccountId))

Seems you have not initialised "mapContactAccount" : because if the query used to populate this map returned no data, the map will not be initialised.


If this solution works for you, please mark it solved to help others .
 
Tyler HarrisTyler Harris
Thank you! I'll try this solution. Does this normally happen when writing Test Classes? Do they normally clash with Triggers?
Tyler HarrisTyler Harris
Tried that and even with the Code update it's still firing the same null.pointer exception on the same line. :(