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
Brian Hopkins 25Brian Hopkins 25 

Replicate the automatic creation of OpportunityContactRole records, in an Apex Test Class?

When an Opportunity is created via a Contact, Salesforce will automatically create an OpportunityContactRole record.

When an after insert trigger is fired, the OpportunityContactRole records are already present.

However I cannot replicate this functionality in my Test Class.  When I insert the opportunity, the trigger fires before I can insert the OpportunityContactRole records, so the test fails.

I need to either:
  • Reproduce that automatic functionality so that the OpportunityContactRole is inserted with the Opportunity
  • Delay the firing of the trigger until after i have inserted the OpportunityContactRole

Triggers can not be added to the OpportunityContactRole object, or I'd have built it that way.
If you are not familiar with this process DO NOT RESPOND.  (I'm sick of getting copy-pasted responses from people who didn't read the question.)
Best Answer chosen by Brian Hopkins 25
Prateek Singh SengarPrateek Singh Sengar
Hi Brian,
There is a workaround that you can try, its not a perfect solution but it might help. 
  • In your trigger which creates your custom record based on opportunitycontactrole.
  • Add a block of code that will execute only in case of test classes execution. The syntax is
if(Test.isRunningTest()){
// manually create an opportunity contact role.
}
  • This block of code should be placed before line 11 where you are querying the OpportunityContactRole
  • ​Now when you execute your test class theoritcally it should execute this block in the trigger and create an opportunitycontactrole and it should work. 
I didnt got chance to try it out so it might take some tweaking to get it work. Hope this helps.

All Answers

swati_sehrawatswati_sehrawat
Hello Brian,

Since you have already written the trigger, can you share the trigger over here and then we can help you in writing test class for the same without copy pasting it from anywhere else :)
Brian Hopkins 25Brian Hopkins 25

Hi Swati, thanks for your response.
 
Here's the function which is called by an after insert trigger on the Opportunity:

/* This function inserts an initial contact role on an opportunity for the contact from which it was created*/
    public static void InitializeContactRoles(Opportunity[] newOpps){

        /* when an opportunity is created, there should be a built-in opportunity contact role created also.  
           query that and use it to fill in a new Contact_Role__c*/
        List<Id> OppIds = new List<Id>();
        for (Opportunity opp: newOpps){
            OppIds.add(opp.Id);
        }
        
        List<OpportunityContactRole> ocrList = [Select Id, ContactId, OpportunityId from OpportunityContactRole where OpportunityId in :OppIds];
        
        List<Contact_Role__c> newRoles = new List<Contact_Role__c>();
        for (OpportunityContactRole ocr : ocrList){
            newRoles.add(new Contact_Role__c(Contact__c=ocr.ContactId, Opportunity__c=ocr.OpportunityId, Roles__c='Sponsor (Coach)'));
        }
        
        insert newRoles;
               
    }
And here is the Test Class I've written:
@isTest
public class Opportunity_TriggerTest {

    public static TestMethod void runTest(){
        Account testAccount = new Account(Name='AxonifyTest89u7245987432897234879324');
        insert testAccount;
        
        Contact testContact = new Contact(LastName='TestContact293847', AccountID=testAccount.Id);
        insert testContact;

        Opportunity testOpp = new Opportunity(Name='TestOpportunity78453757755743566', 
                                              AccountID=testAccount.Id,
                                              StageName = 'Stage F - (ODR/Sales Prospecting)',
                                              CloseDate = Date.today()
                                             );
        insert testOpp;
        
        //Here is where the Trigger Fires
        //It looks up any OpportunityContactRole record on the newly-inserted Opportunity.
        //But because of the context, the OpportunityContactRole is not there yet.
        //The test below therefore fails

        List<Contact_Role__c> results = [Select Id from Contact_Role__c where Opportunity__c = :testOpp.Id];
        
        System.assert(results.size()>0);  // fails because results is empty
    }
}

Thanks.
Prateek Singh SengarPrateek Singh Sengar
Hi Brian,
There is a workaround that you can try, its not a perfect solution but it might help. 
  • In your trigger which creates your custom record based on opportunitycontactrole.
  • Add a block of code that will execute only in case of test classes execution. The syntax is
if(Test.isRunningTest()){
// manually create an opportunity contact role.
}
  • This block of code should be placed before line 11 where you are querying the OpportunityContactRole
  • ​Now when you execute your test class theoritcally it should execute this block in the trigger and create an opportunitycontactrole and it should work. 
I didnt got chance to try it out so it might take some tweaking to get it work. Hope this helps.
This was selected as the best answer
Brian Hopkins 25Brian Hopkins 25
Hi Prateek, Yes I believe that will work for me.  It can get around that automatic function by using a block like that.  
The trigger itself will insert the extra OpportunityContactRole record, and then execute the rest normally.

Thanks for the suggestion, I don't know why I didn't think of that before!
Prateek Singh SengarPrateek Singh Sengar
Hi Brian,
Please mark this thread as solved if the solution works. This was a unique scenario and marking it solved might help others who stumble upon this in future.