Here's a simple test class that illustrates an issue I'm having with a test class that I have been putting together:

public class ForeignKeyConstraintTest

    public static void testReference(){
        list<Contact> cs = [ 
            SELECT Id  
            FROM Contact 
            WHERE Id = '003p0000006PLuG' ];

        list<Opportunity> op = [ 
            SELECT Id  
            FROM Opportunity 
            WHERE Id = '006p0000004w3Q8'  ];  

        insert new OpportunityContactRole( 
            ContactId = '003p0000006PLuG' 
        ,   OpportunityId = '006p0000004w3Q8'  );  

        list<OpportunityContactRole> rs = [ 
            SELECT Id
                 , ContactId
                 , OpportunityId
            FROM OpportunityContactRole  ];  

        System.assertEquals( 0 , cs.size() );
        System.assertEquals( 0 , op.size() );
        System.assertEquals( 1 , rs.size() );
        System.assertEquals( '003p0000006PLuG' , rs[0].ContactId );
        System.assertEquals( '006p0000004w3Q8' , rs[0].OpportunityId );


This works fine in the sandbox, and since this test class is not SeeAllData=true, so I assumed it would work in production as well, since there shouldn't be any data dependencies.

Test methods passed

Unfortunately, when the test runs on a deployment to production, I've been getting an error:


Presumably this is because the referenced records are in the sandbox org, and even though the referenced records aren't visible themselves in the test class, they are somehow available for reference.

Before I change my approach to testing, I wanted to ask the group:

  1. Is there any way to get the referenced record loaded into the test environment with the correct Id value?

I've tried Test.loadData(), but it looks like that doesn't preserve Ids.

  1. Is there some test execution setting to allow lookup fields to have Ids that ignore these foreign key constraints?
  • 1
    quite interesting, You mean to say without SeeAllData=true works in sandbox but didn't worked on prod. have you tried to put the production ids in test class and tried in production if it works or not? – Ratan Paul Aug 9 '18 at 10:27
  • @RatanPaul Right, even though the data isn't visible, somehow the indexes are still exposed in the test environment. – martin Aug 9 '18 at 10:37

Since Id is getting changed from environment to environment. Also, using of hardcoded ids not recommended in classes.

So, one way I would suggest you to create data based on External Id field and keep the reference based on External Id.

Here is an approach, though you can expand this according to your use case.

public class HandoffForm_Test2

    public static void testReference()
        Account acct = new Account(Name = 'test');
        insert acct;

        Contact con = new Contact (AccountId=acct.Id, LastName = 'MyLastName', External_Id__c = 'SomeConId123');
        insert con;

        HandoffFormRole__c hFObj = new HandoffFormRole__c( Name = 'testHandoff' );
        hFObj.Contact__c = con.Id;
        insert hFObj;

        list<HandoffFormRole__c> hs = [SELECT Id, Contact__c, Contact__r.External_Id__c FROM HandoffFormRole__c];

        System.assertEquals( 0 , cs.size() );
        System.assertEquals( 1 , hs.size() );
        System.assertEquals( 'SomeConId123' , hs[0].Contact__r.External_Id__c );


You can also refer following knowledge articles which works on same principle.

Import related records using an External ID and Creating Parent and Child Records in a Single Statement Using Foreign Keys

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.