So i've made two custom fields for account and contact. When the account is updated with Total I want each of the contacts to be given an equal amount of money from the Total so if there's two accounts and total is 100 contacts get 50 each.
I'm not sure where I am going wrong here. I'm new to apex and writing test cases in general too so any help appreciated.
The trigger :
trigger claimTest on Account (after update) {
for(Account a : Trigger.new){
if(a.Total__c != Trigger.oldMap.get(a.id).Total__c){
List<Contact> contactList= [SELECT Share__c FROM CONTACT WHERE Contact.AccountId =: a.id];
List<Contact> contactList1 = new List<Contact>();
Decimal price_total = a.Total__c;
List<AggregateResult> cnt= [SELECT COUNT(Id) countTask FROM CONTACT WHERE Contact.AccountId =: a.id];
Integer tskCount = (Integer)cnt[0].get('countTask');
Decimal divided = price_total/tskCount;
for(contact c:contactList){
c.Share__c = divided;
contactList1.add(c);
}
update contactList1;
}
}
}
The test:
@isTest
public class claimTestTest {
static testMethod void TestAccount()
{
Account a = new Account();
a.Name ='Test Account';
insert a;
Contact cont = new Contact();
cont.FirstName='Test';
cont.LastName='Test';
cont.Accountid= a.id;
insert cont;
Contact cont2 = new Contact();
cont2.FirstName='Testing';
cont2.LastName='Testing';
cont2.Accountid= a.id;
insert cont2;
Account accountToUpdate = new Account();
accountToUpdate = [SELECT Total__c FROM Account WHERE Name='Test Account'LIMIT 1];
accountToUpdate.Total__c = 100;
update accountToUpdate;
System.debug('Share for ' + cont.Share__c);
System.assertEquals(50, cont.Share__c);
}
}
Best Answer
For being new to Apex and unit testing, I'd say you did pretty well. There are, of course, issues, but we'll work those out.
The first big thing that I'm seeing with your trigger is that you're querying inside of a loop. Queries inside of loops are bad, and will cause problems (eventually) because you can only use 100 queries (under normal circumstances) per transaction.
The general pattern to use instead is something like...
That said, we can do something a little different here. Since
Contact
has a lookup toAccount
, we say thatAccount
is the "parent" object andContact
is the "child" object. We can perform a parent-child subquery (aka a left outer join). This provides a few benefits, such as having each relatedContact
automatically correlated to its parentAccount
record and being able to determine how manyContacts
anAccount
has without an additional query.That query looks like this:
We can use that to simplify your trigger.
As far as your unit test goes, the big thing you were missing was already covered by Himanshu. To assert whether or not your
Contacts
were updated with the correct amount inShare__c
, you need to re-query theContacts
. Other than that, your test has all the important things:About the only other thing I can say about your test class is that I'd like to see more test methods in it. Right now, you're testing the 'happy path' where your data is well-formed and won't cause any problems. The real world (once you get actual users involved) is more harsh. Writing tests to cover less-than-ideal situations will give you confidence that your code is not only correct, but that it can also stand up to abuse (i.e. your code is 'robust').
Some additional tests that would be good to write:
Account.Total__c
becomes 0 or negative?Account.Total__c
becomes null?Account
has noContacts
?Account
has only oneContact
?Account
has a couple hundredContacts
?Account.Total__c
can't be evenly divided (e.g. total = 100, 3Contacts
)Each of those would be a different test method.