Mock the Base Apex Class in Tests

When writing unit tests for an extension provider class, sometimes we want to mock the super() method in the extension provider class. However, the Apex test framework does not support mocking objects or methods in a namespace that is different from where test classes are defined. This tutorial provides a workaround to allow us to mock super() in the extension provider class. To learn more about Apex’s namespace, refer to Default Namespaces in Apex on the Salesforce Developers blog.

The idea is to separate the logic for calling the super() default logic so that it can be mocked in the test.

Let’s walk through an example for testing the extension provider class.

Assume we have an extension provider class called Custom_Inventory that extends a Base Apex class CommerceDxSampleapp.CommerceDx_Inventory.

The Base Apex Class has its own namespace and is different from the org of the extension provider class.

Note

Base Apex Class 

The base Apex class looks like this:

1global virtual class CommerceDxSampleapp.CommerceDx_Inventory {
2    global virtual Integer calculateInventoryLevel (String webstoreId, String eventId){
3        // Default Logic
4        return 0;
5    }
6}

Extension Provider Class 

The Custom_Inventory class belongs to current org’s namespace._

Note

To create an extension provider, add a class that extends the base Apex class:

1public class Custom_Inventory extends CommerceDxSampleapp.CommerceDx_Inventory {
2    public override Integer calculateInventoryLevel(String webstoreId, String eventId){
3       // Invoke Base Class's default logic
4       super.calculateInventoryLevel(webstoreId, eventId);
5    }
6}

1. Add "Virtual" to Extension Provider Classes 

To make sure that we can mock the default logic, add a method that only calls super() and make it overridable by marking it as virtual. We also need to mark the class as virtual.

1public virtual class Custom_Inventory extends CommerceDxSampleapp.CommerceDx_Inventory {
2    public override Integer calculateInventoryLevel(String webstoreId, String eventId){
3        return callDefault(webstoreId, eventId);
4    }
5
6    @TestVisible
7    private virtual Integer callDefault(String webstoreId, String eventId){
8        // Invoke Base Class's default logic
9        return super.calculateInventoryLevel(webstoreId, eventId);
10    }
11}

2. Define the Test Class 

Next, define the test class. (See Salesforce Developers to learn how to write an Apex test.)

MyTestClass 

1@isTest
2public class MyTestClass {
3    @isTest
4    public static void testCalculateInventory(){
5
6    }
7}

3. Define the Inner Mock Class 

Finally, define an inner mock class called Fake_Custom_Inventory to override the logic for the super() method that belongs to the base Apex class. Then the test method can use the mock class to return the expected result for the super() logic.

1@isTest
2public class MyTestClass {
3    @isTest
4    public static void testCalculateInventory(){
5        Fake_Custom_Inventory fake_Custom_Inventory = new Fake_Custom_Inventory();
6        // Assert the result is the same as mocked result defined below
7        String webstoreId = 'fakeWebstoreId';
8        String eventId = 'fakeEventId';
9        System.assertEquals(-1, fake_Custom_Inventory.calculateInventoryLevel(webstoreId, eventId));
10    }
11
12    // Create a mock private class in the test class
13    private class Fake_Custom_Inventory extends Custom_Inventory{
14        public override Integer callDefault(String webstoreId, String eventId) {
15            // Return a mocked result for testing
16            return -1;
17        }
18    }
19}