1

I am trying to bring more mocking into our test class. Many of our queries follow the pattern of user.contact__r.patient__c

I am struggling to figure out how to mock this using Apex Mocks. I have not looked at SObject Fabricator yet.

Below is a dummy method fairly representative of common business logic traversing foo.bar__r.baz__c

public with sharing class MyMockExamples {
    UserSelector userSelector;
    public Boolean isUserCool(Set<Id> userIds){
        userSelector = (UserSelector)NorthAmericaApplication.SELECTOR.newInstance(User.SObjectType);
        User user = userSelector.usersWithContactInformation(userIds)[0];
        System.debug(user);
        return user.Contact.Patient__r.Active__c ? true : false;

    }
}

Using the fflib_ApexMocksUtills, I can set values on the contact object. But if it goes up the patient object, it won't compile. I have tried with Patient__c and Patient__r.

static void isUserPatientActive() {
        //given
        fflib_ApexMocks mocks = new fflib_ApexMocks();
        UserSelector mockSelector = (UserSelector) mocks.mock(UserSelector.class);
        User mockUser = new User(Id = fflib_IDGenerator.generate(User.SObjectType));
        Contact mockContact = new Contact();
        Patient__c patient = new Patient__c();
        mockUser = (User) fflib_ApexMocksUtils.setReadOnlyFields(mockUser, User.class,
                new Map<SObjectField, Object>{User.ContactId => fflib_IDGenerator.generate(Contact.SObjectType),
                user.Contact.Name => 'Joe', user.Contact.Patient__c.Active__c => true}) ;
        mocks.startStubbing();
        System.debug(mockUser);
        mocks.when(mockSelector.usersWithContactInformation(new Set<Id>{mockUser.Id})).thenReturn(new List<User>{mockUser});
        mocks.when(mockSelector.sObjectType()).thenReturn(User.SObjectType);
        mocks.stopStubbing();
        NorthAmericaApplication.SELECTOR.setMock(mockSelector);
        //then
        MyMockExamples mockExamples = new MyMockExamples();
        mockExamples.isUserCool(new Set<Id>{mockUser.Id});
    }
}

This works just fine.

Can I do this with Apex Mocks, or do I just need to try and build some JSON strings to serialize?

///Just to leave this for posterity this did indeed pass after SFDXFox help

@IsTest
    static void isUserPatientActive() {
        //given
        fflib_ApexMocks mocks = new fflib_ApexMocks();
        UserSelector mockSelector = (UserSelector) mocks.mock(UserSelector.class);
        User mockUser = new User(Id = fflib_IDGenerator.generate(User.SObjectType));

        Patient__c patient = new Patient__c(Active__c = true, Id = fflib_IDGenerator.generate(Patient__c.SObjectType));
        Contact mockContact = new Contact(Patient__r = patient);
        mockUser = new User(Id = fflib_IDGenerator.generate(User.SObjectType), Contact = mockContact);
        mocks.startStubbing();
        System.debug(mockUser.Contact.Patient__r.Active__c);
        mocks.when(mockSelector.usersWithContactInformation(new Set<Id>{mockUser.Id})).thenReturn(new List<User>{mockUser});
        mocks.when(mockSelector.sObjectType()).thenReturn(User.SObjectType);
        mocks.stopStubbing();
        NorthAmericaApplication.SELECTOR.setMock(mockSelector);
        //then
        MyMockExamples mockExamples = new MyMockExamples();
        Boolean result = mockExamples.isUserCool(new Set<Id>{mockUser.Id});
        Assert.isTrue(result, 'Patient should be active');
    }
}

1 Answer 1

2

Your problem lies here:

new Map<SObjectField, Object>{
  User.ContactId => fflib_IDGenerator.generate(Contact.SObjectType),
  user.Contact.Name => 'Joe', 
  user.Contact.Patient__c.Active__c => true
}) ;

You can't set relationships this way.

Instead, you would mock each record in succession. Mock the Patient__c record, then mock the Contact, setting the Contact.Patient__c field to the newly mocked Patient__c, then mock the User, setting User.Contact in the process.

0

You must log in to answer this question.

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