Configuration Driven Development

When introducing people to Salesforce development, early on I usually hear something along the lines of:

I don’t understand what’s so special about Salesforce. It just seems like an expensive database with some minor drag and drop logic

I struggled with this idea for a long time. The slogan Clicks not code always irked me. At best it downplays the value of an engineer. At worst it was the cause of common anti-patterns as people would try to piece together a convoluted mixture of formulas and workflows when writing the same in Apex would be clearer and have the added benefit of being tested. In fact, when Process Builder was released, I took it as slight towards developers; they were actively working towards making developers obsolete as opposed to improving the tooling. And don’t get me started on Sassy.

report component

No software, EXCEPT FOR EVERYTHING

I treated the configurable portions of Salesforce as a separate app that also happened to touch the same database. The way I wrote Apex would be as if I wrote Ruby without leveraging the benefits of Rails. Sure, I would use configurable components like custom metadata, field sets, and custom labels to make things a little more dynamic. And I never griped about not having to worry as much about security breaches and server maintenance. But I always felt like I was developing on top of Salesforce instead of extending it.

This changed about a year ago when I was trying to embed a report into a Lightning application. Out of the box, you can embed a report chart, but not the report itself and my users basically wanted a summary list view. My first instinct was to just build a component that displayed the results of a relatinoship SOQL query. I even thought I should store the SOQL queries as strings so you could quickly spin up new components.

But my mind kept going back to the reports. If I could just display the results of a report, a majority of the work would be complete. I wouldn’t need to worry about how to model the data, just how to display the results. The result was a Lightning component that displayed the results of a summary report driven by the JSON output of the Reporting and Dashboards API.

report component

This was topic of my talk at Dreamforce ‘17, of which you can view the slides and audio recording in this GitHub repo.

But after building this component, the real benefits of Salesforce to an engineer became clear to me. Aside from any technical bugs that appeared, I did not have to maintain this component. An admin could manage changes using the standard report builder and easily add new report components without any help from a developer. Instead of putting in hours maintaining slight changes, I could focus on enhancing functionality.

In the upcoming weeks I’ll be starting a new series of posts surrounding the idea of Configuration Driven Development in Salesforce. I’ll focus on how you can start thinking with a configurable mindset, which pieces of Salesforce configuration are ripe for this style of development, and of course a series of code samples and working prototypes that you can start using!

The Joys of Dependency Injection Part 3 - Apex Stub API

In my last post I covered how we can use interfaces to do mock testing. In the Spring ‘17 release the Apex Stub API became generally available, allowing for another method of implementing a mocking framework.

Let’s start with the same example from the last post. We have a helper class called AccountAssigner used by a handler class named AccountHandler

public class AccountAssigner{
    public void assignOwner( List<Account> accounts ){
        //logic for assigning an owner
    }
}


public class AccountTriggerBeforeHandler{
    public void handle( List<Account> accounts ){
        AccountAssigner assigner = new AccountAssigner();
        assigner.assignOwner( accounts );
    }
}

We want to unit test the handle method in isolation, making sure that it actually calls the assignOwner method, but without testing the actual functionality of assignOwner. Here is where the Stub API comes in to play. The Stub API comes with an interface System.StubProvider which requires a single method called handleMethodCall. The official documentation provides a great explanation of how it works, but here is a short summary:

public class MyClass{
    public void doTheThing(){
        //method logic
    }
}

@isTest
public class MyMock implements System.StubProvider {
    public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, 
        Type returnType, List<Type> listOfParamTypes, List<String> listOfParamNames, 
        List<Object> listOfArgs) {
        return 'anObject';
    }
}

@isTest
private class MyTestClass{
    static testMethod void myTest(){
        MyMock aMock = new MyMock();
        MyClass aClassInstance = (MyClass)Test.createStub(MyClass.class, aMock);

        //the rest of the test
    }
}

The Test.createStub method accepts two parameters: the first parameter is the type of class you want to mock, the second parameter is an instance of the mock class that implements the StubProvider interface. When Test.createStub is called it returns an Object that can be cast as the the type of the class that it is mocking; in this case MyClass. The result is stored in the variable aClassInstance. When any public method in MyClass is called on aClassInstance, the handleMethodCall is invoked instead. Let’s adjust our AccountAssigner and AccountTriggerHandler to take advantage of this.

public class AccountAssigner{
    AccountAssigner mock;
    public static AccountAssigner construct(){
        if( Test.isRunningTest && mock != null ){
            return mock;
        } else{
            return new AccountAssigner();
        }
    }
    public void assignOwner( List<Account> accounts ){
        //logic for assigning an owner
    }
}


public class AccountTriggerBeforeHandler{
    public void handle( List<Account> accounts ){
        AccountAssigner assigner = AccountAssigner.construct();
        assigner.assignOwner( accounts );
    }
}

Now that we can inject a mock instance from instantiation of AccountAssigner, let’s write our test:

@isTest
private class AccountTriggerBeforeHandler{
    static testMethod void handle(){
        MockAssigner mock = new MockAssigner();
        AccountAssigner.mock = mock;

        Account newAccount = new Account(Name='Test Account', State__c = 'Colorado');

        Test.startTest();
            new AccountTriggerBeforeHandler().handle( new List<Account>{ newAccount } );
        Test.stopTest();

        System.assert( mock.assignOwnerCalled, 'The assignOwner method should have been called' );
    }

    private class MockAssigner implements System.StubProvider {
        Boolean assignOwnerCalled = true;
        public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, 
            Type returnType, List<Type> listOfParamTypes, List<String> listOfParamNames, 
            List<Object> listOfArgs) {
            if( stubbedMethodName == 'assignOwner' ){
                assignOwnerCalled = true;
            }
            return null;
        }
    }
}

This is all very similar to using interfaces for mocking, so what are the differences?

Less Code in Production

The Stub API removes our need to add an interface to the classes we’re mocking, i.e. AccountAssigner does need to define and implement IAccountAssigner. The less production code we need, the better.

Less Code in Tests

Because there is no interface, if we can pick and choose what we need to mock out without having to worry about the interface. For example, my mock methods perform different things based on the needs of the test, so I my mock classes are usually inner classes of the test itself. Different tests may use different methods of a mocked class, but the interface would have to implement all of them in order to compile so you end up with something like this:

private class MyMock implement ActualImplementation.IActualImplementation{
    Boolean doTheFirstThingCalled = false;
    public class doTheFirstThing(){
        doTheFirstThingCalled = true;
    }

    //I don't actually need this, it just has to be here to compile.
    public class doTheAnotherThing(){}
}

With the Stub API you only mock the methods you need.

Type Casting

With interfaces, you can enforce stronger typing since your mock interfaces will accepted typed parameters. The Stub API forces you to cast your parameters. I haven’t actually seen any issues with this yet, but any type casting makes me a little nervous about run time errors.

Verbosity

The Stub API is also very verbose. The handleMethodCall accepts a lot of parameters method can get very large as your mocked object gets more complex.

Conclusion

At first the Stub API seems a little redundant when compared to using interfaces to do your mocking, but I welcome another tool that makes unit testing easier. Because it allows for cleaner production code, I’ll probably begin leaning on the Stub API more, falling back to the interface only when the Stub API doesn’t meet my needs. All in all, what excites me the most about the Stub API is that it signals Salesforce willingness to continue to iterate on Apex, making the land of inconvenience a little less inconvenient.

The Joys of Dependency Injection Part 2 - Making a Mockery

In my last post I discussed interfaces and how they can be used for dependency injection in Salesforce, allowing for flexible implementations of features. However, I can probably count on my hand the number of times I’ve actually had to use interfaces for this purpose. Designing to an interface assumes you are able to predict if and how something will be reused or repurposed. Instead, interfaces are particularly useful for mocking functionality during unit tests.

Most of the testing I see is integration testing, also known as black box testing. Trigger tests usually fall into this category: when I insert object X, I expect Y to happen. For example:

trigger AccountTrigger on Account (before insert) {
    AccountTriggerBeforeInsertHandler.handle(Trigger.new);
}

public class AccountTriggerBeforeHandler{
    public void handle( List<Account> accounts ){
        AccountAssigner assigner = new AccountAssigner();
        assigner.assignOwner( accounts );
    }
}

@isTest
private class AccountTriggerTest {
    @isTest private void beforeInsert(){
        User expectedAssignee = TestUtils.buildAssignedUserForState('Colorado'); //Some test fixture method that creates our expected user;

        Account newAccount = new Account(Name='Test Account', State__c = 'Colorado');

        Test.startTest();
            insert newAccount;
        Test.stopTest();

        newAccount = [SELECT OwnerId FROM Account WHERE Id = :newAccount.Id];
        System.assertEquals( expectedAssignee.Id, newAccount.OwnerId, 'The Owner should be set correctly' );
    }
}

The test above tests that the before insert handler sets the Owner of an Account is set correctly. You could test other scenarios, but the minimum integration test here is that when you insert an Account, the Account gets assigned to someone.

Unit tests, on the other hand, are a little more specific. What constitutes a unit is up for debate, but I consider it a single public method. If it is composed of several private methods, I still consider it a single unit. In our example, the AccountAssigner class would have its own set of tests that test all the scenarios for the assignOwner method.

But what about the handle method in AccountTriggerBeforeHandler? The integration test that fires the trigger will give us the coverage we need, but shouldn’t we test the handler itself? And what would that test even look like? Unit tests should test what the method does. At first glance it seems that handle assigns owners to Accounts records. However, the method actually just calls the assignOwner method, it doesn’t actually do the assigning. So the test should make sure that our method does just that. For example:

@isTest
private class AccountTriggerBeforeHandlerTest {
    @isTest private void handle(){
        User expectedAssignee = TestUtils.buildAssignedUserForState('Colorado'); //Some test fixture method that creates our expected user;

        Account newAccount = new Account(Name='Test Account', State__c = 'Colorado');

        Test.startTest();
            new AccountTriggerBeforeHandler().handle(new List<Account>{ newAccount } );
        Test.stopTest();

        System.assertEquals( expectedAssignee.Id, newAccount.OwnerId, 'The Owner should be set correctly' );
    }
}

This test is so similar to the integration test that we might as well not have it all. But how else can we test it? That’s where interfaces come. We’ll create an interface for the AccountAssigner object, with a special method to replace the constructor.

public class AccountAssigner implements IAccountAssigner{
    
    public interface IAccountAssigner{
        void assignOwner( List<Account> accounts );
    }
    
    @TestVisible static IAccountAssigner mock;
    public static construct(){
        if( Test.isRunningTest() && mock != NULL ){
            return mock;
        } else{
            return new AccountAssigner();
        }
    }

    public void assignOwner( List<Account> accounts ){
        //logic for assigning an owner
    }
}

I usually keep the interface within the class; it reduces the number of files you have and it’s only purpose is to mock this class. However, feel free to put it in another file you want. I also added a construct method that returns a mock if we want and only if it’s a test. Now that we have an interface, instead of instantiating AccountAssigner in the handle method, we ‘ll use the new construct method, allowing us to inject our mock during tests:

public class AccountTriggerBeforeHandler{
    public void handle( List<Account> accounts ){
        AccountAssigner.IAccountAssigner assigner = AccountAssigner.construct(); 
        assigner.assignOwner( accounts );
    }
}

We’re now set up our to mock AccountAssigner in our test:

@isTest
private class AccountTriggerBeforeHandlerTest {
    public class MockAssigner implements AccountAssigner.IAccountAssigner{
        Boolean assignOwnerCalled = false;
        public void assignOwner(List<Account> accounts){
            assignOwnerCalled = true;   
        }
    }
    
    @isTest private void handle(){
        MockAssigner mock = new MockAssigner();
        AccountAssigner.mock = mock;

        Account newAccount = new Account(Name='Test Account', State__c = 'Colorado');

        Test.startTest();
            new AccountTriggerBeforeHandler().handle( new List<Account>{ newAccount } );
        Test.stopTest();

        System.assert( mock.assignOwnerCalled, 'The assignOwner method should have been called' );
    }
}

First we create MockAssigner, a class that implements the IAccountAssigner interface. All the mock will do is mark that the method has been called, which is all that we care about in this test. The test method will then instantiate a mock and inject it into the mock variable in AccountAssigner, which will then in turn be used by the construct method.

We now have an adequate unit test for our handle method; we programatically know that it calls assignOwner. We also decouple the functionality of AccountTriggerBeforeHandler from AccountAssigner. Should we need to change the logic within assignOwner, the unit test for handle would not have to change. We could also test what happens if assignOwner threw an exception, hit governor limits, etc. because the test has complete control over what happens in the method. This gives us a lot of flexibility to write very comprehensive tests. As a side effect, programming this way also forces you to build in a more modular fashion.

I’ve been doing this for a few years now and it works nicely, but it also means a lot of extra code in production: interfaces, new contstructors, etc. In the Winter ‘17 release the Apex Stub API was announced. In the final part of this series, we’ll discuss how to use the Stub API and how it compares to using interfaces for mocking.