0

About trigger :There are two objects student_details__c and department__c. department__c - contains name and no_of_students__c; student_details__c contains name, department(lookup to department object).

when a student is inserted in a department, that respective department needs to increment the no_of_students__field,similarly when department is changed of a student from one dept to other then no_of_students__c needs to be incremented in the new department and decremented from the old department field. no_of_student__c is the total count of students in respect to the department the belong to in each department object.

Trigger

trigger Test on Student_Details__c (after insert, after update,after delete) {

        studentupdatehandler studobj = new studentupdatehandler();

        if(trigger.isinsert)
        {
        studobj.afterinsert(trigger.new);
        }

        if(trigger.isdelete)
        {
        studobj.afterdelete(trigger.old);
        }

       if(trigger.isupdate)
       {
       studobj.afterupdate(trigger.new,trigger.old);
       }    
}

Trigger Handler

public class studentupdatehandler{

     set<id> deptid = new set<id>();  

public void afterinsert(student_details__c[] newstudentslist) {

        list<department__c> newdeptlist = [select id,name,no_of_students__c,(select id from student_details__r) from department__c where id in:forids(newstudentslist)];

        toinsert(newdeptlist);
 } 

     public void afterdelete(student_details__c[] oldstudentslist) {
        list<department__c> olddeptlist = [select id,name,no_of_students__c,(select id from student_details__r) from department__c where id in:forids(oldstudentslist)];

        toupdate(olddeptlist);
 }

    public void afterupdate(student_details__c[] newstudentslist,student_details__c[] oldstudentslist) {

        list<department__c> newdeptlist = [select id,name,no_of_students__c,(select id from student_details__r) from department__c where id in:forids(newstudentslist)];
        toinsert(newdeptlist);


        list<department__c> odeptlist= [select id,name,no_of_students__c,(select id from student_details__r) from department__c where id in:forids(oldstudentslist)];
        toupdate(odeptlist);  

}

Public set<id> forids(student_details__c[] deptlist ){
        set<id> ids = new set<id>();

         for(student_Details__c record: deptlist){

             ids.add(record.Department__c);

            }
return ids;}

Public void toinsert(department__c[] deptlist ){

        for(department__c dept : deptlist){

                   dept.no_of_students__c = dept.no_of_students__c +1;
        }                 
   update deptlist;      
        } 

Public void toupdate(department__c[] odeptlist ){


        for(department__c dept : odeptlist){
                 dept.no_of_students__c = dept.no_of_students__c -1;
             } 
         update odeptlist; 
}


}

TEST CLASS

@istest

private class StudentupdatehandlerTestClass {

    static testMethod void validateupdatechange() {

       Department__c  newdept = new department__c();   
       newdept.name='CSE';
       insert newdept;

       student_details__c newstudent = new Student_details__c();

       newstudent.Name='From TestClass';   
       newstudent.department__c = newdept.id;    



       System.debug('before@@trigger: ' + newdept.no_of_students__c);

       insert newstudent;

       newstudent = [SELECT department__c FROM student_details__c WHERE Id =:newstudent.Id];
       System.debug('after@@trigger: ' + newdept.no_of_students__c);


       System.assertEquals(1 , newdept.no_of_students__c);
    }
}

The test fails and shows

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

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

Class.studentupdatehandler.toinsert: line 61, column 1 Class.studentupdatehandler.afterinsert: line 12, column 1 Trigger.Test: line 12, column 1: []

The line " newstudent.department__c = newdept.id; " in the test class is what causes the error, the test class passes if i comment that line.

3

I think you are running into a setup issue in your test. I would try to use an @testSetup method that inserts your department and students. Then in your actual test method, test your trigger code.

So, something along the lines of this:

    @testSetup
    static void testData()
    {
           Department__c  newdept = new department__c();   
           newdept.name='CSE';
           insert newdept;
    }

    @isTest
    static void validateupdatechange() 
    {

       // retrieve the Id of the department you created in test setup
       Department__c newDept = [SELECT Id, no_of_students__c FROM 
       Department__c LIMIT 1];

       student_details__c newstudent = new Student_details__c();

       newstudent.Name='From TestClass';   
       newstudent.department__c = newDept.Id;     

       System.debug('before@@trigger: ' + newDept.no_of_students__c);
       test.startTest();

       insert newstudent;

       test.stopTest();

       newstudent = [SELECT department__c FROM student_details__c WHERE Id 
              =:newstudent.Id];

       // Need to query again to get the updated field
       newDept = [SELECT no_of_students__c FROM Department__c LIMIT 1];
       System.debug('after@@trigger: ' + newDept.no_of_students__c);


       System.assertEquals(1 , newDept.no_of_students__c);
    }

I just typed this in so I didn't check it for errors or anything. But hopefully, that solves your issue.

  • Thank you this worked, what was i doing wrong? do we need to query each time, because when i comment line "newDept = [SELECT no_of_students__c FROM Department__c LIMIT 1];" in the last, the test fails, isn't the changes reflected on its own? – Niknit Jul 21 '17 at 13:09
  • thank you for your time. How do I test for update scenario? Can/should I be testing by inserting records in a list? – Niknit Jul 21 '17 at 13:10
  • The reason you have to add the extra query is because your original query holds stale data. So you have to run the query again to get the values that were updated in the trigger call in your test. To do an update, you would do something very similar. First, I would insert a different test student without the department in your test setup method, but give it a specific identifier to search for. Then in your test, query for the department and the student you are going to update. Set the department on your student the just like the above test, update instead of insert. – JRiffe Jul 21 '17 at 13:50
  • The original reason the test was failing was because you were inserting the department. Then later, when you insert your student, the update call for your newly inserted department was getting called, which was the active entity. I'm sure someone else can probably explain the life cycle of an execution context. I know it but not enough to explain it coherently. ha – JRiffe Jul 21 '17 at 14:01
  • Thanks JRiffe, just one more thing if you can, umm why do you use limit 1 and WHERE Id =:newstudent.Id in the SOQL query, I typed in new code to test all but it is failing , I am not using any LIMIT or the where ID clause in SOQL query.also i am using list. I feel if i understand the ID and LIMIT use i will understand it best,i thought since only one record is present then why use LIMIT or .id conditions.Thanks again. – Niknit Jul 24 '17 at 10:44

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.