0

I am stuck in scenario while writing logic for my Test class. I am not able to access Contact.AccountId of User created in test case.

I have created a TestUtility class for creating the community user. The code is given below for reference:

public with sharing class TestUtility {

    public static User createUser(String roleId, String profId, String firstName, String lastName){
        User tempUser = prepareUser(roleId, profId, firstName, lastName);
        return tempUser;
    }

    private static User prepareUser(String roleId, String profId, String firstName, String lastName) {  

        String orgId = UserInfo.getOrganizationId();  
        String dateString =   
        String.valueof(Datetime.now()).replace(' ','').replace(':','').replace('-','');  
        Integer randomInt = Integer.valueOf(math.rint(math.random()*1000000));  
        String uniqueName = orgId + dateString + randomInt;  
        User tempUser = new User(  
            FirstName = firstName,  
            LastName = lastName,  
            email = uniqueName + '@sfdc' + orgId + '.org',  
            Username = uniqueName + '@sfdc' + orgId + '.org',  
            EmailEncodingKey = 'ISO-8859-1',  
            Alias = uniqueName.substring(18, 23),  
            TimeZoneSidKey = 'America/Los_Angeles',  
            LocaleSidKey = 'en_US',  
            LanguageLocaleKey = 'en_US', 
            IsActive = true, 
            ProfileId = profId
        );    
        if( String.isBlank(roleId) == false ){
            tempUser.UserRoleId = roleId;
        }
        return tempUser;  
    }

    public static User createCommunityUser(String contactId, String profId, String firstName, String lastName) {
        User tempUser = prepareUser('', profId, firstName, lastName);
        tempUser.ContactId = contactId;
        return tempUser;
    }

    public static Account createAccount(String Name){
        Account portalAccount = new Account(name = Name );
        return portalAccount;
    }
    public static Contact createContact(String firstName, String lastName, String email, String accountId){
        Contact portalContact = new contact(
            FirstName = firstName, 
            LastName = lastName, 
            Email = email, 
            AccountId = accountId
        );
        return portalContact;
    }
}

TestUtility is used for creating account, contact and the community user.

I have made use of this Utility class in my Test class named UserHandlerTest. The code for it looks like below:

@isTest
public class UserHandlerTest {

    @isTest
    public static void createUser(){
        Id profileId = [Select Id From Profile Where Name ='System Administrator'].Id;
        User u = TestUtility.createUser('',profileId,'Fname','Test');
        System.runAs( u ){
            Account acc = TestUtility.createAccount('Test Account');
            insert acc;
        }
    }
    @isTest
    public static void createCommunityUser(){
        Id profileId = [Select Id From Profile Where Name ='CT'].Id;
        Account acc = TestUtility.createAccount('Test Account');
        insert acc;
        Contact con = TestUtility.createContact('test','Contact','[email protected]',acc.Id);
        insert con;      
        User u = TestUtility.createCommunityUser(con.Id,profileId,'Fname','Test');
        system.debug('User Account::: '+u.Contact.AccountId); ***//getting this as null***
        
        Test.startTest();
        UserHandler.deactivateUsers(new List<Id>{acc.Id});
        Test.stopTest();
    }
}

The main class named UserHandler is used to make the user inactive by normal logic as given below:

public class UserHandler {

@future
    public static void deactivateUsers(List<Id> accountIds) {
    
    
    if (accountIds != null && !accountIds.isEmpty()){
        Map<Id, User> usrMap = new Map<Id, User>([SELECT Id, IsActive, Contact.AccountId FROM User WHERE Contact.AccountId IN :accountIds LIMIT 1]); ***//This query returns null in test class debug logs***
                List<User> usersToUpdate = new List<User>();
                for (Id accountId : accountIds) {

                    for (User communityUser : usrMap.values()) {
                        if (communityUser.Contact.AccountId == accountId) {
                            communityUser.IsActive = false;
                            usersToUpdate.add(communityUser);
                            break; // Exit the inner loop
                        }
                    }
                    
                }

                if (!usersToUpdate.isEmpty()) {
                    update usersToUpdate;
                }
         }
    }
}

I am not able to understand why the value of AccountId is seen missing for the user even if I am passing it via utility class.

4
  • Hi there, I can see two main problems in the code. 1. You are creating a user in code, but not actually in the instance. 'Insert user' is never used to create a new user in the salesforce org. 2. The user object does not have Contact lookup. So Contact.AccountId cannot be used in this regard. AFAIK, you cannot create a custom lookup either. You need to user user Ids instead of account Ids in the query. This should solve the problem. Dec 1, 2023 at 9:25
  • Thanks for your response @AsadullahShaikh Do you recommend using Test.isRunningTest() for getting the user directly and executte existing logic for !Test.isRunningTest()? Dec 1, 2023 at 15:36
  • @AsadullahShaikh Is there any better way to write this class, thanks. Dec 1, 2023 at 16:22
  • Hi there, I'll share the updated code in the comment today. Dec 4, 2023 at 7:54

1 Answer 1

0

The issue is here:

User u = TestUtility.createCommunityUser(con.Id,profileId,'Fname','Test');

that calls

public static User createCommunityUser(String contactId, String profId, String firstName, String lastName) {
    User tempUser = prepareUser('', profId, firstName, lastName);
    tempUser.ContactId = contactId;
    return tempUser;
}

The return value from CreateCommunityUser is a User record that will have the value User.ContactId populated because you created the User object with that value.

But, I don't see the test method actually inserting the User

User u = TestUtility.createCommunityUser(con.Id,profileId,'Fname','Test');
insert u;  // missing! see Asadullah's comment #1 that was spot on

But when an object is created via DML, the lookup objects aren't in memory. You'll need to requery the User to get the value of AccountId to use in the debug statement

u = [SELECT Id, Contact.AccountId, Contact.Account.Name FROM User WHERE Id = :u.Id];

Side note

I'd avoid Test.isRunningTest in PROD code as a matter of principle. PROD code is PROD code. Far better solutions involve using interfaces that are mocked in test methods should the need arise

2
  • Thanks for your response @cropredy I tried the above logic by adding another SOQL as below User u = TestUtility.createCommunityUser(con.Id,profileId,'Fname','Test'); u = [SELECT Id, Contact.AccountId, isActive FROM User WHERE LastName='Test' LIMIT 1]; However when I try to fetch Contact.AccountId, It is still null. The Map of usrMap is still null Dec 1, 2023 at 19:46
  • updated answer; I missed the obvious
    – cropredy
    Dec 2, 2023 at 2:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .