+ Start a Discussion
NANCY1NANCY1 

Help needed to write the Test Class for the Trigger...?

Hi,

 

I am not able to understand how can i write the test class for the following trigger. The functionality of the trigger is described below.

 

 

 

trigger updatecurrentallocation on RMG_Employee_Allocation__c (after insert,after update)
{
List<RMG_Employee_Master__c> opps = new List<RMG_Employee_Master__c>();
RMG_Employee_Master__c oppty;
List<ID> masterIds = new List<ID>();
Map<ID, String> childDetailMap = new Map<ID, String>();
for(RMG_Employee_Allocation__c c: Trigger.new)
{
 masterIds.add(c.RMG_Employee_Code__c);
 childDetailMap.put(c.RMG_Employee_Code__c, (c.project__c+'-'+c.Manager_Name__c));
}
opps = [select id, Current_Allocation1__c from RMG_Employee_Master__c where id in :masterIds];
for(RMG_Employee_Master__c rem: opps)
{
  if(rem.Current_Allocation1__c != null)
  {
 String[] semiColonSplittedString = rem.Current_Allocation1__c.split(' ;');
 String[] splittedChildVal = childDetailMap.get(rem.id).split('-');
 Boolean flag = false;
 String tempString1 ='';
 String tempString2 = '';
 for(String s: semiColonSplittedString)
{
tempString1 = s;
tempString1 = tempString1.toLowerCase();
tempString2 = splittedChildVal[0].toLowercase();

if(tempString1.contains(tempString2))
{

system.debug('Current Allocation is   :::::::::   '+rem.Current_Allocation1__c);

system.debug('Map value is :::::::::::::::::::  '+childDetailMap.get(rem.id));
rem.Current_Allocation1__c = rem.Current_Allocation1__c.replace(s, childDetailMap.get(rem.id));

system.debug('Current Allocation after replacement   :::::::::   '+rem.Current_Allocation1__c);
flag = true;
system.debug('Flag is    '+flag);


 

}
}

if(!flag)
    rem.Current_Allocation1__c = rem.Current_Allocation1__c + ' ;'+ childDetailMap.get(rem.id);
  }
 else
   rem.Current_Allocation1__c = childDetailMap.get(rem.id);
}
if(opps.size() > 0)
      Update opps;
}

 

And the functionality of this trigger is as follows:

RMG_Employee_Master__c is a Master object and RMG_Employee_Allocation__c is a child object.

 

In the child object i have two custom field project__c , Manager_Name__c, In the Master object i have a custom field Current_Allocation1__c

 

Current_Allocation1__c i.e. a master object field that gets updated with the Custom object fields and are seperated by "-". Something like project__c1-Manager Name1;project__c2-Manager Name2 and so on...

 

: semicolon is used as an symbol to seperate between each detail records Manager Name and Project code...

 

 

 

SteveBowerSteveBower

Don't think about writing a test case for the trigger.

 

Think about writing a test case that performs the functions you're expecting the users to do, and then check that the results from the trigger occurred as expected.

 

So, in this case, you're trigger is an after insert, after update trigger for a RMC_Employee_Allocation__c record(s).

 

 

So, your test code should:

 

1. Create an RMG_Employee_Master__c record with whatever minimal set of data is needed to just create the record.

2. Insert that record and now you have the ID for the master record.

3. Now create a single RMG_Employee_Allocation__c record with the newly created Id in the RMG_Employee_Code__c field (which points to the master), and some thing in the Project__c and Manager_Name__c fields (perhaps 'Destroy All Humans', and 'Terminator')

4. Now insert the new RMG_Employee_Allocation__c record.

5. No re-query the RMG_Employee_Master__c record you created above.... (you need to re-query it because it's contents should have changed from the trigger..)

6. Now do a system.assertEqual to check that the Current_Allocation1__c field in the RMG_Employee_Master__c record does indeed have 'Destroy All Humans-Terminator' as it's value.

 

that series of steps would test the *simple* case of checking for an insert, with only one record in the trigger, in a case where the Master has no existing data in it.   Additional cases you need/want to check are:

 

B. Do steps 3-6 again with different values in #3 because when you get to #6 you should now have both the Terminator string from the old #3 as well as the new ones in the Master's string (because you're trying to accumulate them.

C. Do an update of one of the child records and make sure the Master was changed...  and that both the old value is gone, and the new value is there.

D. (Your code doesn't handle this case, but I think it will need to), What if you delete one of the Children records... your code doesn't handle "before delete", but it seems it should.

 

E. Bulk.  Instead of doing just one record at a time, create one Master and 200 Children for that single Master.  Verify the Master has all 200 new values after they are inserted.  Note this mean creating 200 children with unique information.  Also, you will may need to check to make sure you don't blow away the length limit on the Current_Allocation1__c field.  (I'm using 200, pick some large number that is meaningful.  In theory 2000 would be a good number as well, but from a practical perspective you may never have more than 10, etc.  However, imagine if, for some reason, you delete all the child records in your system and then re-import them from a backup/dump that you previously made.)

 

F. Bulk for update.  Now update the local copied of the 200 that you just created.  Check the master again.  

 

Other thoughts... in the update case you might first check to see if the values of the two child fields have changed by comparing the values in trigger.new with trigger.old.  Because if the values of the specific fields that you care about hasn't changed, then you don't need to worry about them for this trigger.

 

There are also guidelines in the Apex doc for other avenue of operation to test.  User permissions especially.

 

I'm sure there are more areas to test, but this would give you a good start.   Remember, code coverage isn't sufficient... you need to test the results.

 

Hope this helps, Steve.

 

 

 

JoAnnCulbertsonJoAnnCulbertson

Steve,

 

That was the best explanation of how to write test code - thank you!  I have always struggled with how to write my test classes and how to bulkify them - your post provided a clear straightforward methodology for me that I had been missing.

 

Thank you again!

 

JoAnn

NANCY1NANCY1

Hi,

 

Based on your suggestion i have created a test class with 100% code coverage in sandbox.. but when i try deploying it to production i get an error:  "Code coverage is 0% atleast 1% is required"

 

Please suggest....

 

Now my test class is:

 

@isTest
private class Testupsertmanagername
{

   static testMethod void testTrigger()
   {
   RMG_Employee_Master__c rmg = new RMG_Employee_Master__c(Name='Test');
      insert rmg;
     
      RMG_Employee_Allocation__c rmgallo = new RMG_Employee_Allocation__c(
                                     Name='Test', Manager_Name__c='Unit Test',
                                     RMG_Employee_Code__c=rmg.id);
      insert rmgallo;
      update rmgallo;
     
      RMG_Employee_Master__c newrmg=[select Name, Current_Manager__c from RMG_Employee_Master__c where id = :rmgallo.id];
      System.assertEquals('Unit Test', newrmg.Current_Manager__c);
      }
      }

 

and the trigger is:

 

trigger upsertmanagername on RMG_Employee_Allocation__c (after update)
{
   List<RMG_Employee_Master__c> opps = new List<RMG_Employee_Master__c>();
   List<ID> masterIds = new List<ID>();
   Map<ID, String> childDetailMap = new Map<ID, String>();
   
   for(RMG_Employee_Allocation__c c: Trigger.new)
    {
      masterIds.add(c.RMG_Employee_Code__c);
      childDetailMap.put(c.RMG_Employee_Code__c, (c.Manager_Name__c));
    }
  
   opps = [select id, Current_Manager__c from RMG_Employee_Master__c where id in :masterIds];
   
   for(RMG_Employee_Master__c rem: opps)
    {
      rem.Current_Manager__c = childDetailMap.get(rem.id);
      Update rem;
    }
   
   if(opps.size() > 0)
      Update opps;
}

SteveBowerSteveBower

Hmmm it actually looks right to me....

 

First:  Just to ask obvious questions... are you also deploying the test class to production as well as the Trigger?

When you look at the Debug Log, you should be able to track the progress of the test run and determine where it went off course...  What do you get from there?

 

 

 

Second:  your  "Update rem" statement inside the for loop at the bottom is bad.  You don't need it there because you're issuing an update for Opps after the loop.   Also, putting the update in the loop makes it not-bulk-safe.

 

Third: When you use your childDetailMap, you can't just blindly issue the get.  There may be cases where, for example, even though there are 10 records in trigger.new, there are only 4 record in your map.  After all, what if an RMG_Employee_Allocation__c record is updated, and it doesn't have an RMG_Employee_Code__C value... then it will be null, and your get() will bomb out.  So, you have to check first using childDetailMap.containsKey(rem.id);

 

Fourth: I suggest you get in the habit of adding comments.  They are good. :-)

 

Best, Steve.