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
Kelly Logan (Raptek)Kelly Logan (Raptek) 

runas() limitations - Can't see Account Id from Contact of current user?

So for an Apex test I am using RunAs() to simulate a particular type of user for a VisualForce page controller. The controller filters access to entries by checking the current user's primary Account (school) to only show entries with the same Account.
List<User> uList = [SELECT Id, contactId, contact.accountId FROM User WHERE Id = :UserInfo.getUserId()];
Id currentSchoolId = !uList.isEmpty() ? uList[0].contact.accountId : null;

The code in the controller is working fine, but it can't pass tests because the test user obviously doesn't have a Contact and Account that match the test entries created. My strategy has been to create a new User (u)  with related Contact entry that has the Account set to match the test entries and then use RunAs(u) for the test run.
Account acc = new Account(name='Test College',recordTypeId=AccountRecordTypeInfo .get('College/University').getRecordTypeId());
insert acc;
    
Id genRT = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('General').getRecordTypeId();  
Contact con1 = new Contact(lastName='Contact', firstName = 'Test', recordTypeId=genRT, accountId=acc.Id);
insert con1;

Profile p = [SELECT Id FROM Profile WHERE Name='College - FA&CC Combined'];
User u = new User(Alias = 'standt', Email='standarduser@testorg.com',
    EmailEncodingKey='UTF-8', LastName='Tester', FirstName='FA&CC combo', LanguageLocaleKey='en_US',
    LocaleSidKey='en_US', ProfileId = p.Id, Contact = con1, ContactId = con1.Id,
    TimeZoneSidKey='America/Denver', UserName='standarduser@testorg.com');  
insert u;
u = [Select Id, LastName, ContactId From User Where Id = :u.Id];  
 
Again, this seems to work fine until the Test.startTest(). Once that runs, for some reason contact.accountId comes back null. I tried adding a debug query into the test section. Whether using the :UserInfo.getUserId() or :u.Id the resullt is the same, the User is found and returned, the related Contact Id matches, but the Account Id is null. Before the RunAs() the query returns the correct account, after it the account is blank.
    Test.startTest();
    System.RunAs(u) {

        List<User> uList = [SELECT Id, contactId, contact.accountId FROM User WHERE Id = :u.Id];
        Id currentSchoolId = !uList.isEmpty() ? uList[0].contact.accountId : null;
        System.debug('User Id:' + UserInfo.getUserId());
        System.debug('Queried User:' + uList[0]);
        System.debug('Queried User Id:' + uList[0].Id);
        System.debug('Queried Contact:' + uList[0].contactId);
        System.debug('Queried Account Id:' + uList[0].contact.accountId);
        System.debug('currentSchoolId:' + currentSchoolId);

The goal is to create a test environment where we can call the method above that checks the user's Account. Is this an issue with the RunAs() method? Is there another option? I can change the Account checking query noted above if necessary, but we need to have a way to check it that a test will allow to pass.

 
Kelly Logan (Raptek)Kelly Logan (Raptek)
I have tried running the query after Test.startTest() but before System.RunAs() and the Account Id is returned. Could this be a permissions issue? RunAs() ignores user permissions but not record sharing - do I need to add something else to the Account (acc) entry to make sure the User (u) can access it?
Kelly Logan (Raptek)Kelly Logan (Raptek)
The workaround is to use @isTest(SeeAllData=true), query for a regular user and then base the test data off that user's account instead, then put that user in to the RunAs(). I call this a workaround because I would prefer to use all test data and not touch the regular system.