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
MSVRadMSVRad 

How to Test Trigger Lines containing .addError or for loops

I am writing a test class for a trigger that has multiple for loops in it and When I run the test the lines that are not covered are the for loops.

 

Here is part of the trigger:

trigger AutoCreateIncident on Account (after update) { List<Case> c = new List<Case>(); for (Integer i = 0; i < Trigger.new.size(); i++) { Account newCase = Trigger.new[i]; Account OldCase = Trigger.old[i]; if(newCase.Operational_Status__c == 'Operational' && oldCase.Operational_Status__c == 'IT GO'){ if(newCase.Account_Services_Rep__c == 'Ade Adeyemi' || oldCase.Account_Services_Rep__c == 'Ade Adeyemi'){ for(Integer j = 0; j < 24; j++){ c.add(new Case(Type = 'Health Check', Reason__c = 'Health Check', AccountId = newCase.Id, OwnerId = '005700000016ePl', Priority = 'High', Due_date__c = System.today() + (j*30) + 1)); } } else if(newCase.Account_Services_Rep__c == 'Chris Nelson' || oldCase.Account_Services_Rep__c == 'Chris Nelson'){ for(Integer k = 0; k < 24; k++){ c.add(new Case(Type = 'Health Check', Reason__c = 'Health Check', AccountId = newCase.Id, OwnerId = '005700000016eQ4', Priority = 'High', Due_date__c = System.today() + (k*30) + 1)); } } else if(newCase.Account_Services_Rep__c == 'Deborah Kerr' || oldCase.Account_Services_Rep__c == 'Deborah Kerr' ){ for(Integer l = 0; l < 24; l++){ c.add(new Case(Type = 'Health Check', Reason__c = 'Health Check', AccountId = newCase.Id, OwnerId = '005700000016ePr', Priority = 'High', Due_date__c = System.today() + (l*30) + 1)); } } else if(newCase.Account_Services_Rep__c == 'Elyssa Kim' || oldCase.Account_Services_Rep__c == 'Elyssa Kim'){ for(Integer m = 0; m < 24; m++){ c.add(new Case(Type = 'Health Check', Reason__c = 'Health Check', AccountId = newCase.Id, OwnerId = '00570000001IbB3', Priority = 'High', Due_date__c = System.today() + (m*30) + 1)); } } } } insert c; }

I understand this is not the most efficent or best way to code this trigger, but this is how i have chosen to code it for now. The lines of code that I am not sure how to test are the for loop lines and the "c.add(new Case(" lines. any suggestions on how to tackle this one?

 

I also have another one that has a few Field.addErrors in it and I am not sure how to test those lines of code either 

 

Thanks

Best Answer chosen by Admin (Salesforce Developers) 
Caleb_SidelCaleb_Sidel

To test your inner for loops you will likely need at least 3 test methods. In your test methods you simply have to create test data that meets the criteria. So first:

 

newCase.Operational_Status__c == 'Operational' && oldCase.Operational_Status__c == 'IT GO'

 

You'll need to insert a Case:

 

c.Operational_Status__c = 'Operational';

insert c;

 

c.Operational_Status__c = 'IT GO';

Test.startTest(); 

update c;

Test.stopTest();

 

But you'll also need the other criteria:

newCase.Account_Services_Rep__c == 'Ade Adeyemi' || oldCase.Account_Services_Rep__c == 'Ade Adeyemi'

 

So now you'll need:

c.Operational_Status__c = 'Operational';

c.Account_Services_Rep__c = 'Ade Adeyemi'; 

insert c;

 

c.Operational_Status__c = 'IT GO';

Test.startTest(); 

update c;

Test.stopTest();

 

The above should execute your first for loop and create 24 new Cases.

 

As for optimizing your code, why not make Account_Services_Rep__c a LOOKUP to the User? Then you can simply create 24 new cases where

OwnerId = Account_Services_Rep__c (assuming that Ade Adeyemi has owner id = '005700000016ePl')

 

OR if those aren't the same, why not allow a workflow rule or case assignment rule to make the ownership change for you? Then you don't have to have so many if/else.

 

Your assignment rule could be: If case type = Health Check and Account Services Rep = 'Ade Adeyemi' then assign the case to the owner with id 005700000016ePl.

 

You'd then only have a single inner for loop to test in your test method!

 

Good luck and check out: http://wiki.developerforce.com/index.php/An_Introduction_to_Apex_Code_Test_Methods

 

 

 

All Answers

Caleb_SidelCaleb_Sidel

To test your inner for loops you will likely need at least 3 test methods. In your test methods you simply have to create test data that meets the criteria. So first:

 

newCase.Operational_Status__c == 'Operational' && oldCase.Operational_Status__c == 'IT GO'

 

You'll need to insert a Case:

 

c.Operational_Status__c = 'Operational';

insert c;

 

c.Operational_Status__c = 'IT GO';

Test.startTest(); 

update c;

Test.stopTest();

 

But you'll also need the other criteria:

newCase.Account_Services_Rep__c == 'Ade Adeyemi' || oldCase.Account_Services_Rep__c == 'Ade Adeyemi'

 

So now you'll need:

c.Operational_Status__c = 'Operational';

c.Account_Services_Rep__c = 'Ade Adeyemi'; 

insert c;

 

c.Operational_Status__c = 'IT GO';

Test.startTest(); 

update c;

Test.stopTest();

 

The above should execute your first for loop and create 24 new Cases.

 

As for optimizing your code, why not make Account_Services_Rep__c a LOOKUP to the User? Then you can simply create 24 new cases where

OwnerId = Account_Services_Rep__c (assuming that Ade Adeyemi has owner id = '005700000016ePl')

 

OR if those aren't the same, why not allow a workflow rule or case assignment rule to make the ownership change for you? Then you don't have to have so many if/else.

 

Your assignment rule could be: If case type = Health Check and Account Services Rep = 'Ade Adeyemi' then assign the case to the owner with id 005700000016ePl.

 

You'd then only have a single inner for loop to test in your test method!

 

Good luck and check out: http://wiki.developerforce.com/index.php/An_Introduction_to_Apex_Code_Test_Methods

 

 

 

This was selected as the best answer
dkorba2k5dkorba2k5

Well ... first off, this is not the best way to code this for a couple reasons.  1. You've hardcoded userids in here when you should query for those.  But more importantly 2. You've got way too much coding to accomplish this and it's going to require more test code to cover it.  Take a look at the modified example here:

 

trigger accountsAfterTrigger on Account (after update) {

Case[] c = new Case[0];
Map <Id, Account> newCase = Trigger.newMap;
Map <Id, Account> oldCase = Trigger.oldMap;
Map <String, Id> assignTable = new Map <String, Id> ();
assignTable.put('Ade Adeyemi','005700000016ePl');
assignTable.put('Chris Nelson','005700000016eQ4');
assignTable.put('Deborah Kerr','005700000016ePr');
assignTable.put('Elyssa Kim','00570000001IbB3');

for (Account a : Trigger.new) {
if ((a.Operational_Status__c == 'Operational') &&
(oldcase.get(a.id).Operational_Status__c == 'IT GO') &&
(assignTable.get(a.Owner.Name) != null)) {
for (Integer i = 0; i < 24; i++) {
c.add(new Case(Type = 'Health Check',
Reason__c = 'Health Check',
Accountid = a.id,
ownerid = assignTable.get(a.Owner.Name),
Priority = 'High',
Due_date__c = System.today() + (i*30) + 1
));
}
}
}
if (c.size() > 0) {insert c;}
}

 

 I've simplied your 4 for loops down to a single one.  This way you only have to insert a test account once for the code to get tested vs. the 4 times you would've had to do it before.  All you need for test coverage here to get it to fire at a minimum is the following:

 

 

static testMethod void testAccount() {
Account a = new Account(Name='Test Account',

BillingState='CA',

BillingCountry='US',

  Account_Services_Rep__c = 'Ade Adeyemi'

Operational_Status__c='IT GO');
insert a;

 

a.Operational_Status='Operational';
update a;
}

 The original way you had it, you would've had to do this multiple times (for each account_services_rep__c you have).

 

Now the code I put in here that has the assignTable should really be done with a query to the user table instead but this will work also.

 

 

 

Message Edited by dkorba2k5 on 11-25-2009 09:44 AM
MSVRadMSVRad
Thank you for this solution. I would have preferred for the Account_Services_Rep__c field to be a lookup as it would have made coding this trigger a lot easier, but this just was not an option. I didn't even think about using Case Assignment or Workflow rules. I ended up making use of workflow rules and only needing the one nested for loop.