You need to sign in to do that
Don't have an account?
Jennifer Prather
Rollup Summary Field Class and Trigger
I am trying to test a couple of triggers and classes. I am unable to get the test coverage up to 75%. Here is my classes and triggers:
Here is my test class:
I am not sure how to get the test coverage up. I am having trouble finding a way to test the IF statements.
public class RollUpOrder { public static void upOrder(List<Order> listOfOrder){ Set<id> accountIds = new Set<id>(); List<Account> listOfAccounts = new List<Account>(); List<Order> listOrders = new List<Order>(); For(Order orders : listOrders){ accountIds.add(orders.Id); } List<Account> listAccount = [SELECT Id, Name, Number_of_Orders__c, (SELECT Id FROM Orders) FROM Account WHERE Id IN :accountIds]; For(Account acc : listAccount){ if(acc.Orders.size()>0) acc.Number_of_Orders__c = acc.Orders.size(); listOfAccounts.add(acc); } if(listOfAccounts.size()>0) update listOfAccounts; } }
public class orderCounter { public static void countOrders(Set<Id> accIds){ List<Account> accountsToUpdate = new List<Account>(); Map<Id, Account> accountsMap = new Map<Id, Account>([SELECT Id, Number_of_Orders__c FROM Account WHERE Id IN :accIds]); List<AggregateResult> res = [SELECT AccountId, count(Id) FROM Order WHERE AccountId IN :accIds GROUP BY AccountId]; for(AggregateResult accRes : res){ accountsMap.get(String.valueOf(accRes.get('AccountId'))).Number_of_Orders__c = Integer.valueOf(accRes.get('expr0')); accountsToUpdate.add(accountsMap.get(String.valueOf(accRes.get('AccountId')))); } update accountsToUpdate; } }
trigger RollUpOrderTrigger on Order (after insert, after update, after delete, after undelete) { if(trigger.isAfter && (trigger.isInsert || trigger.isUpdate || trigger.isUndelete)){ RollUpOrder.upOrder(trigger.new); } else if(trigger.isAfter && trigger.isDelete){ RollUpOrder.upOrder(trigger.old); } }
trigger orderCounterTrigger on Order (after insert, after update, after delete) { Set<Id> orderIds = new Set<Id>(); for(Order orders : Trigger.new){ orderIds.add(orders.AccountId); } if(Trigger.isUpdate || Trigger.isDelete){ for(Order ords : Trigger.old){ orderIds.add(ords.AccountId); } } orderCounter.countOrders(orderIds); }
Here is my test class:
@isTest private class TestRollUp { @isTest static void TestOrdRollUp(){ Account newAcc = new Account(Name = 'Test'); insert newAcc; List<Order> newOrder = new List<Order>(); Order newOrd = new Order(Name = 'Test', AccountId = newAcc.Id, EffectiveDate = Date.newInstance(2020,2,3), Status = 'Draft'); newOrder.add(newOrd); insert newOrder; Test.startTest(); newAcc.Number_of_Orders__c = newOrder.size(); update newAcc; Test.stopTest(); newAcc = [SELECT Number_of_Orders__c FROM Account WHERE Id = :newAcc.Id]; System.debug('Number after trigger: ' + newAcc.Number_of_Orders__c); System.AssertEquals(1, newAcc.Number_of_Orders__c); } }
I am not sure how to get the test coverage up. I am having trouble finding a way to test the IF statements.
For example, make a test method called upOrderTest() to test only the code that you've written for your upOrder method. Make a separate test method for orderCounter method. This may seem tedious but this will ensure that your entire code is working as expected. I also suggest bulkifying your code with multiple records. Triggers, if I am not mistaken, can hold up to 200 records at a time before processing the next batch of 200 records if more exist. Thus, in your test code, there should be at least 200 records being inserted and processed.
Also, in your test class, I noticed that you only mention updating records and not not deleting some records. Some of your test triggers are based on if records are deleted so I think you should include some in your test class. I believe this will help test out the rest of your code.
I hope my suggestions were helpful!
I don't know why you have wriiten two triggers for the same purpose. I assume you are trying the different approaches for Counting the Childs in parent via Inner soql and Aggregate functions.
But I have found some issues also in your code.
Issue 1 : Apex Class :
public class RollUpOrder {
public static void upOrder(List<Order> listOfOrder){
Set<id> accountIds = new Set<id>();
List<Account> listOfAccounts = new List<Account>();
List<Order> listOrders = new List<Order>();
For(Order orders : listOfOrder){ /// listOrders ==> listOfOrder wrong list reffered here.
accountIds.add(orders.accountId); /// Here you reffered the Order ID wrongly instead of Account Id
}
List<Account> listAccount = [SELECT Id, Name, Number_of_Orders__c, (SELECT Id FROM Orders) FROM Account WHERE Id IN :accountIds];
For(Account acc : listAccount){
if(acc.Orders.size()>0)
acc.Number_of_Orders__c = acc.Orders.size();
listOfAccounts.add(acc);
}
if(listOfAccounts.size()>0)
update listOfAccounts;
}
}
Issue 2 : In Apex Trigger:
trigger orderCounterTrigger on Order (after insert, after update, after delete) {
Set<Id> orderIds = new Set<Id>();
if(Trigger.isInsert) /// You need the Trigger Context variable check here otherwise you will get Exception in after delete
{
for(Order orders : Trigger.new){
orderIds.add(orders.AccountId);
}
}
else if(Trigger.isUpdate || Trigger.isDelete){
for(Order ords : Trigger.old){
orderIds.add(ords.AccountId);
}
}
orderCounter.countOrders(orderIds);
}
Updated Test Class:
@isTest
private class TestRollUp {
static testmethod void TestOrdRollUp(){
Account newAcc = new Account(Name = 'Test');
insert newAcc;
List<Order> newOrder = new List<Order>();
Order newOrd = new Order(Name = 'Test', AccountId = newAcc.Id, EffectiveDate = Date.newInstance(2020,2,3), Status = 'Draft');
newOrder.add(newOrd);
insert newOrder;
}
static testmethod void TestOrdRollUp1(){
Account newAcc = new Account(Name = 'Test');
insert newAcc;
List<Order> newOrder = new List<Order>();
Order newOrd = new Order(Name = 'Test', AccountId = newAcc.Id, EffectiveDate = Date.newInstance(2020,2,3), Status = 'Draft');
newOrder.add(newOrd);
insert newOrder;
delete newOrder;
}
}
Thanks,
Maharajan.C
In salesforce lookup relatioship we don't have any other better options than Trigger to rollup the childs in parent.
We can use the Flows also for this but you are new so better go with triggers.
In trigger also we can use the multiple approaches to achieve this.
1. Using Inner SOQL.
2. Using Aggregate function.
3. Using Apex collection.
Already you have tried the first two approaches in your above question.
And based on me you can go with the first approach because your code also look fine only small mistakes are in Apex Class. Please use the below updated one:
Apex Trigger:
Apex Class:
Thanks,
Maharajan.C