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
Alaric WimerAlaric Wimer 

Need help with verifying that a bulk insert works in my Test Class

I have a simple rigger that automatically creates a custom PO_Number__c record when an Opportunity is created. This PO_Number__c an Account__c lookup field and an Opportunity__c lookup field that also gets automatically populated by the trigger.

 

In my test class, my first test method singleOpp() succeeds, but I want to test a situation where a builk insert of Opportunities happens. My second test method is bulkOpps(). I'm not sure how to finish this method off to make sure that all the PO_Number__c records that were automatically created have the correct Account__c and Opportunity__c fields.

 

Any help would be greatly appreciated! Here's my code:

 

TRIGGER:
 

trigger createPurchaseOrder on Opportunity (after insert) {
    // Initialize PO Numbers to insert list
    List<PO_Number__c> ponsToInsertList = new List<PO_Number__c>();

    for (Opportunity opp : Trigger.new) {
        if (opp.Id != null && AccountId != null) {
            // Create PO Number records
            PO_Number__c pon   = new PO_Number__c();
            pon.Account__c     = opp.AccountId;
            pon.Opportunity__c = opp.Id;
            ponsToInsertList.add(pon);
        }
        if (!ponsToInsertList.isEmpty()) {
            // Insert PO Number records 
            insert ponsToInsertList;
        }
    }
}


TEST CLASS:
 
@isTest
private class CreatePurchaseOrderTest {
    @isTest static void singleOpp() {
        // Create Account
        Account acc = new Account();
        acc.Name    = 'Test Account';
        insert acc;

        // Create Opportunity
        Opportunity opp = new Opportunity();
        opp.Name        = 'Test Opp';
        opp.CloseDate   = Date.today();
        opp.StageName   = 'Initial Contact';
        opp.AccountId   = acc.Id;
        insert opp;

        // get opp
        List<Opportunity> updatedOpp = [
            SELECT Id, AccountId
              FROM Opportunity
             WHERE Id = :opp.Id
             LIMIT 1
        ];

        // check for PO Number record
        List<PO_Number__c> pon = [
            SELECT Id, Opportunity__c, Account__c
              FROM PO_Number__c
             LIMIT 1
        ];

        System.assertEquals(1, pon.size(), 'pon list size not correct');
        System.assertEquals(updatedOpp.get(0).Id, pon.get(0).Opportunity__c, 'Opportunity on PO Number not correct');
        System.assertEquals(updatedOpp.get(0).AccountId, pon.get(0).Account__c, 'Account on PO Number not correct');
    }

    @isTest static void bulkOpps() {
        // Create multiple Accounts
        List<Account> accList = new List<Account>();
        for (Integer i = 0; i < 500; i++) {
        Account myAcc = new Account();
        myAcc.Name    = 'Test Acc ' + i;
        accList.add(myAcc);
        }
        insert accList;

        // Create multiple Opps
        List<Opportunity> oppList = new List<Opportunity>();
        for (Integer i = 0; i < 500; i++) {
        Opportunity myOpp = new Opportunity();
        myOpp.Name        = 'Test Opp ' + i;
        myOpp.StageName   = 'Initial Contact';
        myOpp.CloseDate   = Date.today();
        myOpp.AccountId   = accList.get(i).Id;
        oppList.add(myOpp);
        }
        insert oppList;

        // Check for PO Number records
        List<PO_Number__c> ponList = [
            SELECT Id, Account__c, Opportunity__c
              FROM PO_Number__c
        ];

        // HOW CAN I DETERMINE IF EACH PO NUMBER HAS THE CORRECT OPPORTUNITY AND ACCOUNT ?????
        // EX: PO Number 1 has Account 1 and Opportunity 1 on it's Account__c and Opportunity__c fields
        // EX: PO Number 1 had Account 2 and Opportunity 2 on it's Account__c and Opportunity__c fields

        System.assertEquals(accList.get(0).Id, ponList.get(0).Account__c, 'Account not correct on PO Number');
        System.assertEquals(oppList.get(0).Id, ponList.get(0).Opportunity__c, 'Opportunity not correct on PO Number');
    }
}

 
Best Answer chosen by Alaric Wimer
Andrew GAndrew G
Hi Alaric

Nothing jumps out but the logic seems sound.

I would try two thing in conjunction:
1.  Reduce the number of created records so whilst we are testing the code logic. It may help to do this a variable so :
Integer recordsToCreate = 10;

//...other code .. adjust loops as:
for (Integer i =0; i< recordsToCreate; i++) { 

//continue with other code
System.assertEquals(recordsToCreate, ponLIst.size(), 'Incorrect amount of PO Numbers created');

2. Stick some debugs into the code, such as (but only once you have reduced the number of records being produced):
for (Integer i = 0; i < ponList.size(); i++) {
           System.debug('**debug integer ' + i);
           System.debug('**debug account name' + ponList[i].Account__c);
           System.debug('**debug Opportunity name' + ponList[i].Opportunity__c);
        }
You should then be able to review the run log and see what is actually produced.  
Other things to maybe consider whould be whether we need to extract the inserted records with a sort order before we generate the other test data.

 

All Answers

Andrew GAndrew G
Hi Alaric

Try the following tweak from line 59
// Check for PO Number records
    List<PO_Number__c> ponList = [
        SELECT Id, Account__c, Opportunity__c
        FROM PO_Number__c
            ORDER BY Account__r.Name, Opportunity__r.Name
    ];

System.assertEquals(500,ponList.size());

for (Integer i = 0; i < ponList.size(); i++) {
    System.assertEquals(accList[i].Id, ponList[i].Account__c, 'Account not correct on PO Number');
    System.assertEquals(oppList[i].Id, ponList[i].Opportunity__c, 'Opportunity not correct on PO Number');
}
Basically, if we order the PO Number list using expected values , in this instance, the name of account and opportunity respectively, we should get the correct order.
We can then loop then entire list, or perhaps just one, to test for the correct value. Or you may even modify the testing loop to be something like:

To reduce the test code run time, you could modify the loop
for (Integer i = 0; i < ponList.size(); i+100) {  - in this way we test every 100th record instead of looping the 500, we only loop 5 times

As a small aside, I generally test explicitly for single or small groups of records.  When I'm doing the bulk test, its usually more about the trigger/code handling the number of records without hitting any sort of limit.  So the test is more about checking that the expected number of records was created, as opposed to the exact test of each of the bulk created test records.

HTH 
 
Alaric WimerAlaric Wimer

Thank you Andrew. Your response was very helpful! I really appreciate you taking the time to explain that to me. I tried out the adjustment today, and was getting the error "Account not correct on PO Number" from the assertion in the for loop. I've been trying to figure out why this happening but am struggling. Is there anything that you can think of that might be causing this?

 

Here's the trigger and the test class (just the bulkOpps method) again:

 

TRIGGER:
 

trigger createPurchaseOrder on Opportunity (after insert) {
    // Initialize PO Numbers to insert list
    List<PO_Number__c> poNumsToInsertList = new List<PO_Number__c>();
    for (Opportunity opp : Trigger.new) {
        if (opp.Id != null && opp.AccountId != null) {
            // Create PO Number records
            PO_Number__c poNum   = new PO_Number__c();
            poNum.Account__c     = opp.AccountId;
            poNum.Opportunity__c = opp.Id;
            poNumsToInsertList.add(poNum);
        }
    }
    if (!poNumsToInsertList.isEmpty()) {
        // Insert PO Number records 
        insert poNumsToInsertList;
    }
}

TEST CLASS (bulkOpps method):
 
@isTest static void bulkOpps() {
        // Create multiple Accounts
        List<Account> accList = new List<Account>();
        for (Integer i = 0; i < 500; i++) {
            Account myAcc = new Account();
            myAcc.Name    = 'Test Acc ' + i;
            accList.add(myAcc);
        }
        insert accList;

        // Create multiple Opps
        List<Opportunity> oppList = new List<Opportunity>();
        for (Integer i = 0; i < 500; i++) {
        Opportunity myOpp = new Opportunity();
            myOpp.Name        = 'Test Opp ' + i;
            myOpp.StageName   = 'Initial Contact';
            myOpp.CloseDate   = Date.today();
            myOpp.AccountId   = accList.get(i).Id;
            oppList.add(myOpp);
        }
        insert oppList;

        // Check for PO Number records
        List<PO_Number__c> ponList = [
            SELECT Id, Account__c, Opportunity__c
              FROM PO_Number__c
          ORDER BY Account__r.Name, Opportunity__r.Name
        ];

        System.assertEquals(500, ponList.size(), 'Incorrect amount of PO Numbers created');

        for (Integer i = 0; i < ponList.size(); i++) {
            System.assertEquals(accList[i].Id, ponList[i].Account__c, 'Account not correct on PO Number');
            System.assertEquals(oppList[i].Id, ponList[i].Opportunity__c, 'Opportunity not correct on PO Number');
        }
    }

 
Andrew GAndrew G
Hi Alaric

Nothing jumps out but the logic seems sound.

I would try two thing in conjunction:
1.  Reduce the number of created records so whilst we are testing the code logic. It may help to do this a variable so :
Integer recordsToCreate = 10;

//...other code .. adjust loops as:
for (Integer i =0; i< recordsToCreate; i++) { 

//continue with other code
System.assertEquals(recordsToCreate, ponLIst.size(), 'Incorrect amount of PO Numbers created');

2. Stick some debugs into the code, such as (but only once you have reduced the number of records being produced):
for (Integer i = 0; i < ponList.size(); i++) {
           System.debug('**debug integer ' + i);
           System.debug('**debug account name' + ponList[i].Account__c);
           System.debug('**debug Opportunity name' + ponList[i].Opportunity__c);
        }
You should then be able to review the run log and see what is actually produced.  
Other things to maybe consider whould be whether we need to extract the inserted records with a sort order before we generate the other test data.

 
This was selected as the best answer
Alaric WimerAlaric Wimer
Thank you Andrew! I went ahead with your suggestion about extracting the inserted records with a sort order and it worked. I appreciate your help on this.