+ Start a Discussion
Chad RitchieChad Ritchie 

WritingTestClass

Pretty new to writing test classes, was looking for help for this trigger:

trigger SumPositions on Investor__c (before insert, before update, before delete) {
    for (Investor__c record : Trigger.new) {
        record.Sum_of_Positions__c = null;
    }
    for(AggregateResult result: [SELECT SEI_Investor_Id__c, SUM(Position__c.Balance__c)
                                 FROM Position__c WHERE SEI_Investor_Id__c
                                 IN :Trigger.newMap.keyset() GROUP BY SEI_Investor_Id__c]) {
         Trigger.newMap.get(result.get('SEI_Investor_Id__c')).Sum_of_Positions__c = (Decimal)result.get('expr0');
     }
 }
Best Answer chosen by Chad Ritchie
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
Hey, Chad -- I notice that your Investor__c trigger will throw an exception if you ever delete an Investor__c record, because Trigger.new does not exist on delete triggers.  I'm not sure you mean to update the rollup field on delete (perhaps you meant undelete); but in case you do, here's a technique you can use:

<pre>
trigger SumPositions on Investor__c ( before insert, before update, before delete )
{
    List<Investor__c> records = Trigger.isDelete ? Trigger.old : Trigger.new;
    Map<Id,Investor__c> recordsMap = Trigger.isDelete ? Trigger.oldMap : Trigger.newMap;
    for ( Investor__c record : records )
    {
        record.Sum_of_Positions__c = null;
    }

    for ( AggregateResult result :
        [   SELECT  SEI_Investor_Id__c, SUM(Balance__c) sumPositions
            FROM    Position__c
            WHERE   SEI_Investor_Id__c IN :records
            GROUP BY SEI_Investor_Id__c
        ]
        )
    {
        recordsMap.get( (Id) result.get( 'SEI_Investor_Id__c' ) ).Sum_of_Positions__c =
            (Decimal) result.get( 'sumPositions' );
     }
}
</pre>

All Answers

Nathan EhrmannNathan Ehrmann
Hi Chad,

Basically, your test class should do the following

1. create and insert Investor records (check the Sum of Positions, is it zero as expected?)
2. create and insert Positions
3. update your investor records (check their sum of Positions, are they updated?)

That pretty much sums it up (no pun intended). I'm happy to write out some actual code if that's what you're looking for.
Nathan EhrmannNathan Ehrmann
@isTest
private class TestSumPositions{

	private static testmethod void sumPositionCheck(){

		Investor__c inv1 = new Investor__c();
		INSERT inv1;

		Investor__c inv2 = new Investor__c();
		INSERT inv2;

		List<Investor__c> invs = [SELECT Id, Sum_of_Positions__c FROM Investor__c];
		
		//checking to make sure everything initializes just fine
		
		System.assertEquals(2, invs.size());
		System.assertEquals(null, invs[0].Sum_of_Positions__c);
		System.assertEquals(null, invs[1].Sum_of_Positions__c);

		//now let's add some positions

		Position__c p1 = new Position__c(SEI_Investor_Id__c = inv1.Id, Balance__c = 100);
		Position__c p2 = new Position__c(SEI_Investor_Id__c = inv2.Id, Balance__c = 100);
		Position__c p3 = new Position__c(SEI_Investor_Id__c = inv2.Id, Balance__c = 150);
		INSERT p1;
		INSERT p2;
		INSERT p3;
		
		//update our original investor records to activate the trigger again		

		for(Investor__c inv : invs){
			inv.Sum_of_Positions__c = 10; //just updating the sum field 
                                          //since I don't know any of the other fields, 
                                          //it will get overwritten anyway
		}
		
		UPDATE invs;

		Map<Id, Investor__c> invMap = new Map<Id, Investor__c>([SELECT Id, Sum_of_Positions__c FROM Investor__c]);
		
		System.assertEquals(100, invMap.get(inv1.Id).Sum_of_Positions__c);
		System.assertEquals(250, invMap.get(inv2.Id).Sum_of_Positions__c);

	}
}

 
Chad RitchieChad Ritchie
Thank you very much, what would a test class look like for this trigger, which fires on the child level, not parent level? I imagine pretty similar. Thanks in advance!!

Trigger SumP on Position__c (after insert, after update, after delete) {
 
Set<Id> investorIds = new Set<Id>();
    List<Investor__c> investorsToUpdate = new List<Investor__c>();
 
    if (!Trigger.isDelete) {
        for (Position__c p : Trigger.new) {
            investorIds.add(p.SEI_Investor_Id__c);
        }
    }
 
    if (Trigger.isUpdate || Trigger.isDelete) {
        for (Position__c p : Trigger.old) {
            investorIds.add(p.SEI_Investor_Id__c);
        }
    }
 
 
    Map<id, Investor__c> popMap = new Map<id,Investor__c>([select id, Sum_of_Positions__c from Investor__c where id IN :investorIds]);
 
    List<AggregateResult> ars = [SELECT SEI_Investor_Id__c, count(Id) FROM Position__c WHERE SEI_Investor_Id__c IN :investorIds GROUP BY SEI_Investor_Id__c];
   
    for (AggregateResult ar : ars) {
        popMap.get((id)ar.get('SEI_Investor_Id__c')).Sum_of_Positions__c = (Decimal)ar.get('expr0');
        investorsToUpdate.add(popMap.get((id)ar.get('SEI_Investor_Id__c')));
    }
 
    update investorsToUpdate;
}
Steven NsubugaSteven Nsubuga
Pretty much the same way
@isTest
public class SumPositionsTest{
        
	@isTest static void testSumPositions(){

		// Create Investor__c for use in testing
		Investor__c investor = new Investor__c();
		
		// populate the necessary fields
		investor.Name = 'Some Investor';
		insert investor;
		
		List<Position__c> positions = new List<Position__c>();
		for (Integer i = 1; i < 5; i++){
			Position__c p = new Position__c();
			
			// populate the necessary fields
			p.SEI_Investor_Id__c = investor.Id;
			positions.add(p);
		}
		insert positions;	
		Investor__c i = [SELECT Id, Sum_of_Positions__c  FROM Investor__c LIMIT 1];
		System.assertEquals(4 ,i.Sum_of_Positions__c);

		delete positions[3];
		
		Investor__c j = [SELECT Id, Sum_of_Positions__c  FROM Investor__c LIMIT 1];
		System.assertEquals(3 ,j.Sum_of_Positions__c);
	}
}

 
Chad RitchieChad Ritchie
The test did work, unforuntately it returned 0/1 methods passed and the trigger code coverage was 0/14, not sure why that is.
Maharasi EzhilarasanMaharasi Ezhilarasan
Hi,

Make sure you have added all required field on insert of position reocrds and check the debug log. You could find the issue.
@isTest
public class SumPositionsTest{
        
  @isTest static void testSumPositions(){

    // Create Investor__c for use in testing
    Investor__c investor = new Investor__c();
    
    // populate the necessary fields
    investor.Name = 'Some Investor';
    insert investor;
    
    List<Position__c> positions = new List<Position__c>();
    for (Integer i = 1; i < 5; i++){
      Position__c p = new Position__c();
      
      // populate the necessary and required fields
      p.SEI_Investor_Id__c = investor.Id;
      p.Balance__c= 100+i;
      positions.add(p);
    }
    insert positions; 

    positions[0].Balance__c=100;
    positions[1].Balance__c=200;
    positions[2].Balance__c=300;
    Update positions;

    Investor__c i = [SELECT Id, Sum_of_Positions__c  FROM Investor__c LIMIT 1];
    System.assertEquals(4 ,i.Sum_of_Positions__c);

    delete positions[3];
    
    Investor__c j = [SELECT Id, Sum_of_Positions__c  FROM Investor__c LIMIT 1];
    System.assertEquals(3 ,j.Sum_of_Positions__c);
  }
}

 
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
Hey, Chad -- I notice that your Investor__c trigger will throw an exception if you ever delete an Investor__c record, because Trigger.new does not exist on delete triggers.  I'm not sure you mean to update the rollup field on delete (perhaps you meant undelete); but in case you do, here's a technique you can use:

<pre>
trigger SumPositions on Investor__c ( before insert, before update, before delete )
{
    List<Investor__c> records = Trigger.isDelete ? Trigger.old : Trigger.new;
    Map<Id,Investor__c> recordsMap = Trigger.isDelete ? Trigger.oldMap : Trigger.newMap;
    for ( Investor__c record : records )
    {
        record.Sum_of_Positions__c = null;
    }

    for ( AggregateResult result :
        [   SELECT  SEI_Investor_Id__c, SUM(Balance__c) sumPositions
            FROM    Position__c
            WHERE   SEI_Investor_Id__c IN :records
            GROUP BY SEI_Investor_Id__c
        ]
        )
    {
        recordsMap.get( (Id) result.get( 'SEI_Investor_Id__c' ) ).Sum_of_Positions__c =
            (Decimal) result.get( 'sumPositions' );
     }
}
</pre>
This was selected as the best answer
Andrew GuptaAndrew Gupta
Being beginner to writing testclass had a query like this but followed answers helped me to get through the trigger.