Apex Mocks is a mocking framework used in Salesforce development, particularly useful for unit testing Apex classes that depend on other classes or external services. It’s built on top of the popular Java mocking framework, Mockito, and is part of the FinancialForce Apex Common library. Here’s a basic tutorial on how to use Apex Mocks in a Salesforce org that isn’t utilizing the fflib enterprise patterns. The focus will be on creating a simple mock for testing purposes without the broader architecture of fflib enterprise patterns.
Prerequisites
- Install Apex Mocks: You need to install Apex Mocks in your Salesforce org. This can usually be done by deploying the necessary classes from its GitHub repository: FinancialForce Apex Mocks.
- Basic Understanding of Apex: Familiarity with Apex programming is assumed.
Step 1: Create an Interface
Apex Mocks works by mocking interfaces, so the first step is to define an interface that your class will implement.
public interface IContactService { List<Contact> findContactsByAccountId(Id accountId); }
Step 2: Implement the Interface in a Class
Now, create a class that implements this interface.
public class ContactService implements IContactService { public List<Contact> findContactsByAccountId(Id accountId) { return [SELECT Id, Name, Email FROM Contact WHERE AccountId = :accountId]; } }
Step 3: Write Test Class with Apex Mocks
Now, let’s write a test class using Apex Mocks to mock the ContactService
.
Create a Test Class: Start by defining a test class and setting up the mock.
@isTest private class ContactServiceTest { static testMethod void testFindContactsByAccountId() { // Initialize the mocks process fflib_ApexMocks mocks = new fflib_ApexMocks(); // Create a mock for the IContactService interface IContactService mockContactService = (IContactService) mocks.mock(IContactService.class); // Set up the mock behavior Id testAccountId = '001xxxxxxxxxxxx'; // Use a suitable test ID List<Contact> expectedContacts = new List<Contact>{ new Contact(Id = '003xxxxxxxxxxxx', Name = 'Test Contact', Email = 'test@example.com') }; // Define the behavior of the mock when the method is called mocks.startStubbing(); mocks.when(mockContactService.findContactsByAccountId(testAccountId)) .thenReturn(expectedContacts); mocks.stopStubbing(); // Inject the mock into the class or method being tested ContactService service = new ContactService(); Test.startTest(); // Replace actual call with the mock System.assertEquals(expectedContacts, service.findContactsByAccountId(testAccountId)); Test.stopTest(); // Optionally verify the behavior was executed ((fflib_IMocksControl)mocks).verify(mockContact
As you can see, there is some refactoring of the actual class needed in order for it to be ‘mock test friendly’. Once an interface is created, it is easily able to be mocked. Happy coding.