SoC and the Apex Common Library Tutorial Series Part 17: Implementing Unit Tests with the Apex Mocks Library

What is Apex Mocks?

Apex Mocks is unit test mocking framework for Apex that was inspired by the very popular Java Mockito framework. The Apex Mocks framework is also built using Salesforce’s Stub API which is a good thing, there are mocking frameworks in existence that do not leverage the Stub API… you shouldn’t use them as they are considerably less performant. In fact, as a remnant of the past, Apex Mocks still has an option to not use the Stub API, don’t use it.

To make this super simple, Apex Mocks is an excellent framework that allows you to not only create mock (fake) versions of your classes for tests, but also allows you to do a number of other things like create mock (fake) records, verify the amount of times a method was called, verify method call order and lots more. There is not another mocking framework for the Apex language that is anywhere near as robust.


Do you have to use the Apex Common Library to use Apex Mocks?

While you don’t have to use the Apex Common Library to use Apex Mocks, they are built to work extremely well together. Without the use of the Apex Common Library you will need to ensure that all of your classes utilize dependency injection. While this isn’t a massive feat, it’s something you have to be cognizant of. If you decide to use the Apex Common library and leverage the the fflib_Application class factory you can leverage the setMock methods to avoid needing to setup all your classes using dependency injection. It’s pretty convenient and makes the whole situation a bit easier. We’ll take a look at both methods below:

Using Apex Mocks without Apex Common Example

//Class we're testing
public with sharing class SoC_Class
{
	private DomainClass domainLayerClass;
	private SelectorClass selectorLayerClass;

	public SoC_Class(){
		//This is calling our private constructor below
		this(new domainLayerClass(), new selectorLayerClass());
	}

	//THE MAJOR DIFFERENCE IS HERE! We're using a private constructor here so our test class can pass in dependencies we would
	//like to mock in our unit tests
	@TestVisible
	private SoC_Class(DomainClass domainLayerClass, SelectorClass selectorLayerClass){
		this.domainLayerClass = domainLayerClass;
		this.selectorLayerClass = selectorLayerClass;
	}

	public List<Case> updateCases(Set<Id> objectIds){
		//Because of our dependency injection in the private constructor above we can mock the results of these class calls.
		List<Case> objList = selectorLayerClass.selectByIds(objectIds);
		if(!objList.isEmpty()){
			List<Case> objList = domainLayerClass.updateCases(objList);
			return objList;
		}
		else{
			throw new Custom_Exception();
		}
	}
}
//Test class
@IsTest
public with sharing class SoC_Class_Test
{
    @IsTest
    private static void updateCases_OppListResults_UnitTest(){
        Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
        Set<Id> caseIds = new Set<Id>{mockCaseId};
        List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', Status = 'New', Origin = 'Email')};
        List<Case> updatedCaseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Panther', Status = 'Chocolate', Origin = 'Email')};

        fflib_ApexMocks mocks = new fflib_ApexMocks();
        DomainClass mockDomain = (DomainClass) mocks.mock(DomainClass.class);
        SelectorClass mockSelector = (SelectorClass) mocks.mock(SelectorClass.class);
        mocks.startStubbing();
        mocks.when(mockSelector.selectByIds(caseIds)).thenReturn(caseList);
        mocks.when(mockDomain.updateCases(caseList)).thenReturn(updatedCaseList);
        mocks.stopStubbing();

        Test.startTest();
        //THE MAJOR DIFFERENCE IS HERE! We are passing in our mock classes we created above to the private constructor that is only
                //visible to tests to leverage dependency injection for mocking.
        List<Case> updatedCases = new SoC_Class(mockDomain, mockSelector).updateCases(caseIds);
        Test.stopTest();

        System.assertEquals('Panther', updatedCases[0].Subject, 'Case subject not updated');
        ((Cases)mocks.verify(mockDomain, mocks.never().description('This method was called but it shouldn\'t have been'))).createOpportunities();
        ((Cases)mocks.verify(mockDomain)).updateCases(caseList);
    }
}

If you take a look at the above SoC_Class class you can see that we are leveraging the concept of dependency injection to allow our SoC_Class_Test test class the ability to inject the mock classes during our unit test. This is the key difference. All of your classes MUST LEVERAGE DEPENDENCY INJECTION to be able to incorporate unit test mocking into your codebase. Now let’s take a look at how to do the same thing using the Apex Common Library and the fflib_Application class.


Using Apex Mocks with Apex Common Example

//Example Application factory class. This is only here because it is referenced in the classes below.
public with sharing class Application
{
	public static final fflib_Application.UnitOfWorkFactory UOW =
		new fflib_Application.UnitOfWorkFactory(
			new List<SObjectType>{
			Case.SObjectType,
			Contact.SObjectType,
			Account.SObjectType,
			Task.SObjectType}
	);

	public static final fflib_Application.ServiceFactory service =
			new fflib_Application.ServiceFactory(
					new Map<Type, Type>{
							Task_Service_Interface.class => Task_Service_Impl.class}
			);

	public static final fflib_Application.SelectorFactory selector =
			new fflib_Application.SelectorFactory(
					new Map<SObjectType, Type>{
							Case.SObjectType => Case_Selector.class,
							Contact.SObjectType => Contact_Selector.class,
							Task.SObjectType => Task_Selector.class}
			);

	public static final fflib_Application.DomainFactory domain =
			new fflib_Application.DomainFactory(
					Application.selector,
					new Map<SObjectType, Type>{Case.SObjectType => Cases.Constructor.class,
					Contact.SObjectType => Contacts.Constructor.class}
			);


}
//Class we're testing
public with sharing class Task_Service_Impl implements Task_Service_Interface
{
    public void createTasks(Set<Id> recordIds, Schema.SObjectType objectType)
    {
                //THE MAJOR DIFFERENCE IS HERE! Instead of using constructors to do dependency injection
                //we are initializing our classes using the fflib_Application factory class. 
        fflib_ISObjectDomain objectDomain = Application.domain.newInstance(recordIds);
        fflib_ISObjectSelector objectSelector = Application.selector.newInstance(objectType);
        fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance();
        List<SObject> objectsThatNeedTasks = new List<SObject>();
        if(objectSelector instanceof  Task_Selector_Interface){
            System.debug('Selector an instance of tsi');
            Task_Selector_Interface taskFieldSelector = (Task_Selector_Interface)objectSelector;
            objectsThatNeedTasks = taskFieldSelector.selectRecordsForTasks();
        }
        else{
            System.debug('Selector not an instance of tsi');
            objectsThatNeedTasks = objectSelector.selectSObjectsById(recordIds);
        }
        if(objectDomain instanceof Task_Creator_Interface){
            System.debug('Domain an instance of tci');
            Task_Creator_Interface taskCreator = (Task_Creator_Interface)objectDomain;
            taskCreator.createTasks(objectsThatNeedTasks, unitOfWork);
        }
        try{
            unitOfWork.commitWork();
        }
        catch(Exception e){
            throw e;
        }
    }
}
public with sharing class Task_Service_Impl_Test
{
    @IsTest
    private static void createTasks_CasesSuccess_UnitTest(){

        Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);

        Set<Id> caseIds = new Set<Id>{mockCaseId};
        List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', Status = 'New', Origin = 'Email')};

        fflib_ApexMocks mocks = new fflib_ApexMocks();
        fflib_SObjectUnitOfWork mockUOW = (fflib_SObjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);
        Cases mockCaseDomain = (Cases) mocks.mock(Cases.class);
        Case_Selector mockCaseSelector = (Case_Selector) mocks.mock(Case_Selector.class);


        mocks.startStubbing();
        mocks.when(mockCaseSelector.sObjectType()).thenReturn(Case.SObjectType);
        mocks.when(mockCaseSelector.selectSObjectsById(caseIds)).thenReturn(caseList);
        mocks.when(mockCaseSelector.selectRecordsForTasks()).thenReturn(caseList);
        mocks.when(mockCaseDomain.sObjectType()).thenReturn(Case.SObjectType);
        ((fflib_SObjectUnitOfWork)mocks.doThrowWhen(new DmlException(), mockUOW)).commitWork();
        mocks.stopStubbing();

        //THE MAJOR DIFFERENCE IS HERE! Instead of dependency injection we are using our
                //the setMock method in the fflib_Application class to set our mock class for unit tests.
        Application.UOW.setMock(mockUOW);
        Application.domain.setMock(mockCaseDomain);
        Application.selector.setMock(mockCaseSelector);


        try{
            Test.startTest();
            Task_Service.createTasks(caseIds, Case.SObjectType);
            Test.stopTest();
        }
        catch(Exception e){
            System.assert(e instanceof DmlException);
        }


        ((Cases)mocks.verify(mockCaseDomain, mocks.never().description('This method was called but it shouldn\'t have 
                 been'))).handleAfterInsert();
        ((Cases)mocks.verify(mockCaseDomain)).createTasks(caseList, mockUOW);
    }
}

As you can see, in this example we no longer leverage dependency injection to get our mock unit tests up and running. Instead we use the setMock method available on all of the inner factory classes in the fflib_Application class to setup our mock class for our unit test. It makes things a bit easier in the long run.

Now that we’ve seen how to setup a mock class with or without Apex Common, let’s figure out all the cool things Apex Mocks has to allow you to assert your logic operated in the way you anticipated it would! We’ll start with a section on what stubbing is below!


What is Stubbing and how to Stub

Soooooo, what exactly is stubbing? Basically it’s the act of providing fake return responses for a mocked class’s methods and it’s super extra important when setting up your unit tests because without them, well frankly nothing is gonna work. So let’s check out how to do stubbing below:

Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', Status = 'New', Origin = 'Email')};

//Creating the mock/fake version of our case selector class
fflib_ApexMocks mocks = new fflib_ApexMocks();
Case_Selector mockCaseSelector = (Case_Selector) mocks.mock(Case_Selector.class);

//Here is where we start stubbing our fake return values from our methods that will be called by the actual class we are testing.
//You need to initialize our mock stubbing by using the mocks.startStubbing method.
mocks.startStubbing();
mocks.when(mockCaseSelector.sObjectType()).thenReturn(Case.SObjectType);
mocks.when(mockCaseSelector.selectSObjectsById(caseIds)).thenReturn(caseList);
//This is basically saying, "hey, when the method we're testing calls the selectRecordsForTasks method on our mocked case selector
//please always return this caseList."
mocks.when(mockCaseSelector.selectRecordsForTasks()).thenReturn(caseList);
mocks.stopStubbing();
//Don't forget to stop stubbing!! Very importante!

//Make sure to do your stubbing before sending your mock class to your application factory class!!!
Application.selector.setMock(mockCaseSelector);

//Doing the test of the actual method that will call those mocked class's stubbed methods above. Make sure to create the mock classes and the stubbed
//method responses for your classes before doing this test!
Test.startTest();
Task_Service.createTasks(caseIds, Case.SObjectType);
Test.stopTest();

Alright, let’s go over this a bit (and if you didn’t read the comments in the code outlined above please do!). The first thing you should know is that you should only be creating stubbed methods for methods that are actually called by the real method you are actually testing (in our case, the Task_Service.createTasks method). Now that we’ve clarified that, let’s break down one of our stubs that we built out for the methods in our mocked class. Take this stub ‘mocks.when(mockCaseSelector.selectRecordsForTasks()).thenReturn(caseList);’, what we are efficitively saying here is, when our mockCaseSelector’s selectRecordsForTasks method is called, let’s always return the caseList value. Not too complicated but maybe confusing if you’ve never seen the syntax before.

Hopefully this has helped explain the basic concept of stubbing alright, there’s more we can do with stubbing in regards to throwing fake errors, so be sure to check out the, “How to mock exceptions being thrown” section below for more information on that subject.


How to verify the class you’re actually testing appropriately called your mock class methods

If you’ve never done mocking before this might seem super weird, instead of using asserts, we need another way to verify that our code functioned as anticipated with our fake classes and return values. So what exactly do you verify/assert in your test? What we’re gonna end up doing is verify that we did indeed call the fake methods with the parameters we anticipated (or that we didn’t call them at all). So let’s take a look at how to use the verify method in the fflib_ApexMocks class to verify a method we intended to call, did indeed get called:

Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
//Creating a set of ids that we pass to our methods.
Set<Id> caseIds = new Set<Id>{mockCaseId};
//Creating the list of cases we'll return from our selector method
List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', Status = 'New', Origin = 'Email')};

//Creating our mock class representations by using the ApexMocks class's mock method
//and passing it the appropriate class type.
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_SObjectUnitOfWork mockUOW = (fflib_SObjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);
Cases mockCaseDomain = (Cases) mocks.mock(Cases.class);

mocks.startStubbing();
mocks.when(mockCaseDomain.sObjectType()).thenReturn(Case.SObjectType);
mocks.stopStubbing();

Application.UOW.setMock(mockUOW);
Application.domain.setMock(mockCaseDomain);

Test.startTest();
//Calling the method we're actually testing (this is a real method call)
Task_Service.createTasks(caseIds, Case.SObjectType);
Test.stopTest();

//THIS IS IT!!! HERE IS WHERE WE ARE VERIFYING THAT WE ARE CALLING THE CASE DOMAIN CREATE TASKS CLASS ONCE!!!
((Cases)mocks.verify(mockCaseDomain, 1)).createTasks(caseList, mockUOW);

On the very last line of the above code we are using the verify method to ensure that the createTasks method in the Cases class was called exactly one time with the caseList and mockUOW values passed to it. You might be looking at this and thinking, “But why Matt? Why would I actually care to this?”. The answer is pretty simple. Even though your code in those classes isn’t running, you still want to (really need to) verify that your code still decided to call it (or not call it), that you code didn’t call the method more times than you were anticipating, etc. Remember, the major purpose of a unit test is to test that the logic in your class is working how you anticipate it to. Verifying that methods were called correctly is extremely important. If your class calls the wrong methods at the wrong time, super ultra terrible consequences could end up taking place.


How to verify your data was altered by your class when it was sent to a mocked class (Matchers)

Whoooo that’s a long title, lol. Here’s the dealio, at least half the time the data you pass into the class you are actually testing (the one class we aren’t mocking) it will altered and then sent in to another mocked class’s method to be further processed. Chances are you’d like to verify that data was altered prior to sending it to your mocked classes method. Never fear my good ole pals, the fflib_Match class is here to help you do just that! Let’s take a look at how we can use matchers to identify what exactly was passed into our mocked class’s methods!

Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
List<Case> caseList = new List<Case>{new Case(
                                     Id = mockCaseId, 
                                     Subject = 'Hi', 
                                     Status = 'New', 
                                     Origin = 'Email')};

fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_SObjectUnitOfWork mockUOW = (fflib_SObjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);
Application.UOW.setMock(mockUOW);

Test.startTest();
//Calling the method we're actually testing (this is a real method call). IN THIS METHOD WE ARE CHANGING THE CASE SUBJECTS FROM 'Hi' to 'Bye'
new Cases().changeSubject(caseList);
Test.stopTest();

//Here we are using the fflib_Match class to create a new sobject to match against to verify the subject field was actually changed in the above method //call.
List<Case> caseMatchingList = (List<Case>)fflib_Match.sObjectsWith(new List<Map<Schema.SObjectField, Object>>{new Map<SObjectField, Object>{
				Case.Id => mockCaseId,
				Case.Subject => 'Bye',
				Case.Status => 'New',
				Case.Origin => 'Email'}
});

//Here we are verifying that our unit of works registerDirty method was indeed called with the updated data we expected by using a matcher. This should //return true pending your code actually did update the cases prior to calling this method as you intended. 
((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW)).registerDirty(caseMatchingList);

//This also works (confusing right)... but it proves a lot less, it simply proves your method was called with that list of cases, but it doesn't prove it //updated those cases prior to calling it.
((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW,1)).registerDirty(caseList);

Alright alright alright, you might be looking at this and being like, “But bruh why make a matcher at all to get this done? Why not just keep it simple and make another list of cases to represent the changes”. Fair enough question hombre, here’s the simple answer… it’s not gonna work, trust me, lol. Basically ApexMocks needs a way to internally check these events actually occurred and that matcher we setup is the key to doing that. If you wanna dive deep into how it works feel free, but that is a whole different subject we’re not gonna get into the weeds of.

So we can see, I think, that this is extremely useful in terms of verifying our logic occurred in the right order and updated our data as anticipated before calling the method in one of our mocked classes. Pretty cool, makes our unit testing that much more accurate.

There are a ton more methods in the fflib_Match class that you can leverage to do virtually whatever you can think of, there’s a list of those near the bottom of this page. Definitely check them out.


How to mock exceptions being thrown (this is THA BEST!!)

If you don’t care about time savings for test runs to get your code into production, you should pick up mocking to allow for easier exception testing at the very least. IT IS SO MUCH EASIER TO VERIFY EXCEPTIONS!!!! A magical thing that honestly can’t be beat. Tons of errors that you should rightfully handle in a ton of situations (like record locking errors) are borderline impossible to test with real data… this makes it possible. Some people out there might be like, “Hah, but I don’t even catch my exceptions why should I care?”. To that I say, time to change my guy, lol, you need to catch those bad boiz, trust me. Anywhooo, let’s get right to it! How do we mock our exceptions to make testing exceptions so simple and so glorious? Let’s checkout the code below:

Here’s an example of mocking an error when the method returns nothing:

fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_SObjectUnitOfWork mockUOW = (fflib_SObjectUnitOfWork) mocks.mock(fflib_SObjectUnitOfWork.class);

mocks.startStubbing();
//This right here is what's doing the mock error throwing!! Basically we're saying, when the commitWork method in our
//mockUOW class is called by the method we are truly testing, please throw a new DMLException. 
((fflib_SObjectUnitOfWork)mocks.doThrowWhen(new DmlException(), mockUOW)).commitWork();
mocks.stopStubbing();

Application.UOW.setMock(mockUOW);

try{
    Test.startTest();
    //Calling the method we're actually testing (this is a real method call)
    Task_Service.createTasks(caseIds, Case.SObjectType);
    Test.stopTest();
}
catch(Exception e){
    //Because we are throwing an exception in our stubs we need to wrap our real
    //method call in a try catch and figure out whether or not it actually threw the
    //exception we anticipated it throwing.
    System.assert(e instanceof DmlException);
}

Here’s a similar example but with a method that returns data:

fflib_ApexMocks mocks = new fflib_ApexMocks();
Case_Selector mockCaseSelector = (Case_Selector) mocks.mock(Case_Selector.class);

mocks.startStubbing();
//These two methods must be stubbed for selectors if using apex common library
mocks.when(mockCaseSelector.sObjectType()).thenReturn(Case.SObjectType);
mocks.when(mockCaseSelector.selectSObjectsById(caseIds)).thenReturn(caseList);

//This right here is what's doing the mock error throwing!! Basically we're saying, when the selectRecordsForTasks method in our
//mockCaseSelector class is called by the method we are truly testing, please throw a new DMLException. 
mocks.when(mockCaseSelector.selectRecordsForTasks()).thenThrow(new DmlException());
mocks.stopStubbing();

Application.selector.setMock(mockCaseSelector);

try{
    Test.startTest();
    //Calling the method we're actually testing (this is a real method call)
    Task_Service.createTasks(caseIds, Case.SObjectType);
    Test.stopTest();
}
catch(Exception e){
    //Because we are throwing an exception in our stubs we need to wrap our real
    //method call in a try catch and figure out whether or not it actually threw the
    //exception we anticipated it throwing.
    System.assert(e instanceof DmlException);
}

You can see that there’s a small difference between the two. For the method that actually returns data the chain of events is a bit easier to follow mocks.when(mockCaseSelector.selectRecordsForTasks()).thenThrow(new DmlException());. This basically is just saying, when we call the mock selector class’s selectRecordsForTasks class then we need to throw a new DMLException.

For the method that doesn’t return any data (a void method) the syntax is a little different ((fflib_SObjectUnitOfWork)mocks.doThrowWhen(new DmlException(), mockUOW)).commitWork(). You can see that instead of using the mocks.when(method).thenThrow(exception) setup we are now using the doThrowWhen method, which kinda combines the when(method).thenThrow(exception) into a single statement. You can also see it takes two parameters, the first is the exception you want to throw and the second is the mocked class you are attaching this exception throwing event to. Then you have to cast this mocks.doThrowWhen(exception, mockedClass) to the class type it will end up representing, wrap it in parenthesis and call the method you intend it to throw an error on. Weird setup, awesomely simple exception testing though.

Also worth noting, don’t forget to wrap methods you are truly testing (that will now throw an error) in a try catch in your test and in the catch block, assert that you are getting your exceptions throw.


How to test important method side-effects truly occured (Answering)

It is not at all uncommon to have parameters passed into a method by reference and for that method to update those parameters but not pass them back. Some people refer to this as method side effects. To truly do good unit tests however we should mock those side effects as well. That is where the fflib_Answer interface comes into play! Now, unlike most things I’ve written about in this series, there is a blog post by Eric Kintzer that already exists for this apex mocks topic that is excellent and well… frankly I don’t need to re-invent the wheel here. Please go check out how to do Answering with Apex Mocks here. .


How to check method call order

Sometimes when you are doing unit tests it’s extremely important to verify the order in which your methods were called. Maybe, depending on what data your method receives your mock class’s methods could be called in varying orders. It’s best to check that the code is actually doing that! If you do need to check for that in your code, no worries, that is why the fflib_InOrder class exists! Thankfully this is yet another area I really don’t need to cover again in this guide as a good blog post exists covering this topic as well! If you need to check method ordering in your unit testing, please check out the blog post here!


Apex Mocks Counters (Counting method calls and adding descriptions)

Counters counters counters… they’re one of the simplest things to learn thankfully and also very useful! Basically you might want to know how many times a method in a mock class was called by the class you are currently unit testing. It helps to verify the logic in your code is only calling classes in the way you intended for it to call it. The syntax is pretty simple so lets get to learninnnnnnnn.

When we are verifying method calls (as discussed in one of the above sections) we do the following:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW)).registerDirty(caseMatchingList);

What if we wanna check whether the code operated only once though? We can check pretty easy by passing a second parameter to the verify method like so:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.times(1))).registerDirty(caseMatchingList);

The above code will verify that our method was not just called, but only called once. Pretty kewl right? But wait! There’s more! Let’s check out a bunch of different counter scenarios below.

How to verify a method was called at least x times:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.atLeast(3))).registerDirty(caseMatchingList);

How to verify a method was called at most x times:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.atMost(3))).registerDirty(caseMatchingList);

How to verify a method was called never:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.never())).registerDirty(caseMatchingList);

How to verify a method was called between x amount of times:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.between(1,5))).registerDirty(caseMatchingList);

Wow wow wow, so many options for so many scenarios, however I would be remiss if I didn’t also should you the description method call you can chain to basically give you useful verification failure statements. Let’s check that out right quick:

((fflib_ISObjectUnitOfWork)mocks.verify(mockUOW, mocks.times(2).description('Whoa champ, you didnt call this dirty method twice, try again broseph'))).registerDirty(caseMatchingList);

If your verification fails (and in turn your test class fails) you will now get that wonderful description to help you pinpoint the cause of your test failure a bit easier. That’s pretty awesome opposum.

Additional Info on Counters


How to generate fake data with Apex Mocks

If we couldn’t produce fake records to pass to our mocked class methods to handle, honestly this whole setup would only be kinda good because we’d always be forced to do real DML transactions in our tests to create data, and if you didn’t know the reason tests can take sooooooooooooo long is because of DML transactions. They take a crazy amount of time in comparison to everything else in your code (unless you’ve got quadruple inner for loops in your codebase somewhere… which you should address like right now, please stop reading this and fix it). So let’s figure out how to make fake data using the Apex Mocks Library.

The first class on our list in the Apex Mocks library to check out is the fflib_IDGenerator class. Inside this class there is a single method, generate(Schema.SObjectType sobjectType) and its purpose is to take an SObjectType and return an appropriate Id for it. This is super useful because if you need to fake that a record already exists in the system, or that a record is parented to another record, you need an Id. You’ll likely use this method a ton.

Example method call to get a fake (but legal) Id:

Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);

That will return to you a legal caseId! Pretty useful.

The next class on our list to cover here is the fflib_ApexMocksUtils class. This class has three accessible methods and they allow you to make in memory relationships between fake records and to setup formula field values for a fake record. Let’s take a look at some examples below.

makeRelationship(Type parentsType, List<SObject> parents, SObjectField relationshipField, List<List<SObject>> children) Example method call:

//Example from: https://salesforce.stackexchange.com/questions/315832/mocking-related-objects-using-fflib
Opportunity opportunityMock1 = new Opportunity(Id = fflib_IDGenerator.generate(Opportunity.SObjectType));

//This basically creates a list of opportunities with child opportunity line items in the list in the OpportunityLineItems field
List<Opportunity> opportunitiesWithProductsMock = (List<Opportunity>) fflib_ApexMocksUtils.makeRelationship(
        List<Opportunity>.class,
        new List<Opportunity>{
                opportunityMock1
        },
        OpportunityLineItem.OpportunityId,
        new List<List<OpportunityLineItem>>{
                new List<OpportunityLineItem>{
                        new OpportunityLineItem(Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType)),
                        new OpportunityLineItem(Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType))
                }
        }
);

makeRelationship(String parentTypeName, String childTypeName, List<SObject> parents, String relationshipFieldName, List<List<SObject>> children) Example method call:

//This is basically the same method as above, but you can pass in String to determine the object and relationship instead of types. I would
//use the method above unless this one was 110% necessary.
List<Opportunity> opportunitiesWithProductsMock = (List<Opportunity>) fflib_ApexMocksUtils.makeRelationship(
        'Opportunity',
        'OpportunityLineItem',
        new List<Opportunity>{
                opportunityMock1
        },
        'OpportunityId',
        new List<List<OpportunityLineItem>>{
                new List<OpportunityLineItem>{
                        new OpportunityLineItem(Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType)),
                        new OpportunityLineItem(Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType))
                }
        }
);

setReadOnlyFields(SObject objInstance, Type deserializeType, Map properties) Example method call:

//Code from: https://github.com/apex-enterprise-patterns/fflib-apex-mocks
Account acc = new Account();
Integer mockFormulaResult = 10;
//This will allow you to set read only fields on your objects, such as the formula field below. Pretty useful!
acc = (Account)fflib_ApexMocksUtils.setReadOnlyFields(
		acc,
		Account.class,
		new Map<SObjectField, Object> {Account.Your_Formula_Field__c => mockFormulaResult}
);

Example Apex Mocks Classes

Task_Service_Impl_Test – Apex Mocks test class example that uses the Apex Common library.


Next Section

That’s it! You’re done! Thank god… I’m tired of writing this thing. You can go back to the home page here.

SoC and the Apex Common Library Tutorial Series Part 16: Unit Test Mocks with Separation of Concerns

How does Unit Testing fit into Separation of Concerns?

The answer to this is simple, without Separation of Concerns, there is no unit testing, it just simply isn’t possible. To unit test you need to be able to create stub (mock) classes to send into your class you are testing via dependency injection (or through the use of a factory, more on this in the next section). If all of your concerns are in one class (DML transactions, SOQL queries, service method, domain methods, etc) you cannot fake anything. Let’s take a look at a couple examples to illustrate this problem:

Unit Testing a class with SoC Implemented

//This is the class we would be testing
public with sharing class SoC_Class
{
	private DomainClass domainLayerClass;
	private SelectorClass selectorLayerClass;

	public SoC_Class(){
		//This is calling our private constructor below
		this(new domainLayerClass(), new selectorLayerClass());
	}

	//Using a private constructor here so our test class can pass in dependencies we would
	//like to mock in our unit tests
	@TestVisible
	private SoC_Class(DomainClass domainLayerClass, SelectorClass selectorLayerClass){
		this.domainLayerClass = domainLayerClass;
		this.selectorLayerClass = selectorLayerClass;
	}

	public List<Case> updateCases(Set<Id> objectIds){
		//Because of our dependency injection in the private constructor above we can 
                //mock the results of these class calls.
		List<Case> objList = selectorLayerClass.selectByIds(objectIds);
		if(!objList.isEmpty()){
			List<Case> objList = domainLayerClass.updateCases(objList);
			return objList;
		}
		else{
			throw new Custom_Exception();
		}
	}
}

//This is the class that we build to unit test the class above
@IsTest
public with sharing class SoC_Class_Test
{
	@IsTest
	private static void updateCases_OppListResults_UnitTest(){
		//Creating a new fake case id using the IdGenerator class. We do this
		//to avoid unnecessary dml insert statements. Note how the same id is used 
                //everywhere.
		Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
		//Creating a set of ids that we pass to our methods.
		Set<Id> caseIds = new Set<Id>{mockCaseId};
		//Creating the list of cases we'll return from our selector method
		List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', 
                Status = 'New', Origin = 'Email')};
		List<Case> updatedCaseList = new List<Case>{new Case(Id = mockCaseId, Subject 
                = 'Panther', Status = 'Chocolate', Origin = 'Email')};

		//Creating our mock class representations by using the ApexMocks class's mock 
                //method and passing it the appropriate class type.
		fflib_ApexMocks mocks = new fflib_ApexMocks();
		DomainClass mockDomain = (DomainClass) mocks.mock(DomainClass.class);
		SelectorClass mockSelector = (SelectorClass) mocks.mock(SelectorClass.class);

		//After you've setup your mocks above, we need to stub (or setup the expected
		//method calls and what they would return.
		mocks.startStubbing();

		//This is the actual selectByIds method that we call in the
		//createNewOpportunities method that we are testing
		//Here we are setting up the fake return result it will return.
		mocks.when(mockSelector.selectByIds(caseIds)).thenReturn(caseList);

		mocks.when(mockDomain.updateCases(caseList)).thenReturn(updatedCaseList);

		//When you are done setting these up, DO NOT FORGET to call the stopStubbing 
                //method or you're gonna waste hours of your life confused
		mocks.stopStubbing();

		Test.startTest();
		//Passing our mock classes into our private constructor
		List<Case> updatedCases = new SoC_Class(mockDomain, 
                mockSelector).updateCases(caseIds);
		Test.stopTest();

		System.assertEquals('Panther', updatedCases[0].Subject, 
                                    'Case subject not updated');
		//Verifying this method was never called, we didn't intend to call it, so
		//just checking we didn't
		((Cases)mocks.verify(mockDomain, mocks.never().description('This method was 
                called but it shouldn\'t have been'))).createOpportunities();
		//Checking that we did indeed call the createTasks method as expected.
		((Cases)mocks.verify(mockDomain)).updateCases(caseList);
	}
}

Above you can see we are passing in fake/mock classes to the class we are testing and staging fake return results for the class methods we are calling. Thanks to separating out our concerns this is possible. Let’s take a look at how impossible this is without SoC in place.

Unit Testing a class without SoC Implemented

//This is the class we would be testing
public with sharing class No_SoC_Class
{
	public List<Case> updateCases(Set<Id> objectIds){
		//Because of our dependency injection in the private constructor above we can 
                //mock the results of these class calls.
		List<Case> objList = [SELECT Id, Name FROM Case WHERE Id IN: objectIds]
		if(!objList.isEmpty()){
			for(Case cs: objList){
				cs.Subject = 'Panther';
				cs.Status = 'Chocolate';
			}

			update objList;
			return objList;
		}
		else{
			throw new Custom_Exception();
		}
	}
}

@IsTest
public with sharing class No_SoC_Class_Test
{
	@TestSetup
	private static void setupData(){
		Case newCase = new Case(Subject = 'Hi', Status = 'New', Origin = 'Email');
		insert newCase;
	}

	@IsTest
	private static void updateCases_CaseListResults_IntegrationTest(){
		Set<Id> caseIds = new Map<Id, SObject>([SELECT Id FROM Case]).keySet();
		List<Case> updatedCases = new No_SoC_Class().updateCases(caseIds);
		System.assertEquals('Panther', updatedCases[0].Subject, 'Case subject not 
                updated');
	}
}

You can see above we did no mocking… it wasn’t possible, we had no way of passing in fake/mock classes to this class at all so we had to do an integration test where we create real data and update real data. This test will run considerably slower.


How do I transition my Existing Code to start leveraging SoC so I can use Unit Test Mocking?

It’s not a simple path unfortunately, there is a lot of work ahead of you to start this transition, but it is possible. The key is to start small, if you are a tech lead the first thing you need to do is find the time to train your devs on what SoC and mocking is and why you would use it. It’s critical they understand the concepts before trying to roll something like this out. You cannot do everything as a lead even if you’d like to, you need to build your team’s skillset first. If you aren’t a lead, you first need to convince your lead why it’s critical you start taking steps in that direction and work to get them onboard with it. If they ignore you, you need a new lead… After accomplishing either the above you should do the following:

1) Frame your situation in a way that the business arm of your operation understands the importance of altering your code architecture to leverage SoC and unit testing. This is typically pretty easy, just inform them that by spending a few extra points per story to transition the code you are going to gain more robust testing (resulting in less manual tests) and that the code will become more flexible over time, allowing for easier feature additions to your org. Boom, done, product owner buy in has been solidified. Ok, lol, sometimes it’s not quite this easy, but you know your business people, give them something they won’t ignore, just be careful to not make yourself or your team sound incompetent, don’t overcommit and make promises you can’t keep and frame it in words business people understand (mostly dollar signs).

2) Start small, take this on a story by story basis. Say you have a new story to update some UI in your org, with business owner buy-in, tack on a few extra points to the story to switch it to start using SoC and Unit Testing. Then, MAKE SURE YOUR TESTS ARE INCREDIBLE AND YOU TRUST THEM! I say this because, if your tests are incredible you never have to ask for permission again… I mean think about it, wtf does the average business person know about code. As long as I don’t introduce any new bugs I could change half the code base and they’d never even know. If your tests are golden, your ability to change on a whim is as well. Make those test classes more trustworthy than your dog (or cat I guess… but I wouldn’t trust a cat).

3) Over time, your transition will be done… it might take a year, it might take 5 years, depends on how busted your codebase was to begin with. Hopefully, by the time you are done, you have an extremely extensible codebase with tests you can trust and you never have to ask for permission to do a damn thing again.


Additional Information

If the above didn’t make how to implement mocking via separation of concerns any clearer, I also have a video covering the subject here.


Next Section

Part 17: Implementing Mock Unit Testing with Apex Mocks

SoC and the Apex Common Library Tutorial Series Part 15: The Difference Between Unit Tests and Integration Tests

What is Unit Testing?

Unit Testing, is a way to test the logic in one class and ONLY one class at a time. Most classes in your system at some point do one of the following:

1) Call to another class to get some work done.
2) Query the database directly in the class.
3) Do DML transactions directly in the class.

However, in unit testing, we ideally don’t want to do any of those things, we don’t care if the querying or the DML transactions or the calls to those other classes work, because what we want to test is that the logic of our class works in every theoretical permutation we can think of AND THAT’S IT! We just want to know if our logic, that we designed for this one class actually works as we anticipate it to work.

You might be thinking, “How is that possible? We need those queries and those dml statements and those classes to successfully run our code!”. Well that my friends is simply not true. With the implementation of separation of concerns and by leveraging one of the many available mocking frameworks we can fake all of those things to build true unit tests.


When Should I use Unit Testing?

Just because you are leveraging unit testing doesn’t mean there still isn’t a need for integration tests (more on that below), so when should you do Unit Tests in favor of Integration tests? It’s a pretty simple answer. The logic in your class’s code could have 40+ paths it could take… maybe even 100… The code in your class could have logic that runs when your code fails, logic that runs when your codes successful, logic that runs when someone creates a $200,000,000 opportunity as opposed to a $2,000 opportunity. There could be so many paths. We DO NOT need an integration test for every single one of those paths. It could take 20+ minutes to run integration tests for all those paths whereas unit testing them could take just seconds. As your codebase grows, if you didn’t make these unit tests your test class runs to deploy to prod could take hours… maybe days… we don’t want that homie. So when do you unit test? You unit test to test the bajillions of permutations of your class’s logic. When do we choose integration tests?? Keep reading. You’ll find out below.

An additional benefit to unit testing/mocking responses is testing hard to test or impossible to test error catching scenarios. One common scenario that I find myself frequently building error catching around is record locking… but how on earth can you test that with real data at run time? It’s borderline impossible, however unit testing makes testing for errors a breeze. It’s so easy you’ll cry, lol, the dream of 100% code coverage can go from just a dream to a very real and easily obtainable thing with unit tests and mocking.


What is Integration Testing?

Integration testing is when you test your code from point A all the way to point Z. What I mean by that is, you actually have your code in your test classes doing SOQL statements, DML transactions, calling the other classes it depends on, etc. Basically your code is truly calling all the real logic from beginning to end, no mocking or fake return results anywhere. Integration testing is what 90%+ of Salesforce orgs seem to do 100% of the time and that is one dangerous game to play. The majority of your tests should not be integration tests… maybe like 20% of them or so. If 100% of your test classes are integration tests, over time you’ll suffer from long test execution and deployment times (or alternatively poorly tested code to reduce those times). If you’ve ever been stuck in a 6+ hour deployment, I think you know what I mean… and what if one test fails during that deploy?… it really hurts, lol. Please, don’t get me wrong though, you can not replace integration tests with unit tests, they are of equal importance, it’s just important that you only use integration tests when needed.


When Should I use Integration Testing?

All apex classes should have some level of integration testing. I like to write somewhere around 20% of my tests as integration tests and 80% of my tests for a class as unit tests. Typically I will, for each class that has dependencies (classes that the class I’m currently testing calls) write two integration tests for each dependency. One integration test that tests a successful path through my classes code and its dependencies and another that tests failures. This may be, in some peoples opinion, overkill, but I personally feel that it’s not an enormous amount of overhead (typically) and it gives me some piece of mind that all of the classes my class I’m testing depends on still operate well with it. So, when to use integration testing? In my opinion, in every test class, but use them sparingly, use them to check that your transactions between classes still work, don’t use them to test every logical path in your class’s code. That will spiral out of control.


Next Section

Part 16: Unit Test Mocks with Separation of Concerns

SoC and the Apex Common Library Tutorial Series Part 14: Implementing the Selector Layer with the Apex Common Library

The Template for every Selector Class you create

Every Selector layer class you create should at least implement the following methods for it to work as anticipated.

//Selector layer classes should all use the inherited sharing keyword so that the caller //determines to context it operates in.
//It should also always extend the fflib_SObjectSelector so it can inherit that classes //methods and functionality.
public inherited sharing class Contact_Selector extends fflib_SObjectSelector
{
	public Contact_Selector(){
                /*This is calling the fflib_SObjectSelector classes constructor and setting 
                  the following booleans:
                  1) If the selector queries should use field sets
                  2) If you would like to enforce CRUD security
                  3) If you would like to enforce FLS
                  4) If you would like to sort selected fields
                */
		super(false, true, true, false);
	}

        //Add the base fields for the object that should just be used in absolutely every 
        //query done by this class
	public List<Schema.SObjectField> getSObjectFieldList(){
		return new List<Schema.SObjectField>{
				Contact.Id,
				Contact.Name,
				Contact.FirstName,
				Contact.LastName
		};
	}

        //Allows you to easily get the object type for the object being queried by this class
	public Schema.SObjectType getSObjectType(){
		return Contact.SObjectType;
	}

        //Allows you to create a query that selects records by a set of ids (basically adds 
        //the WHERE Id IN :ContactIds to the query)
	public List<Contact> selectById(Set<Id> contactIds){
		return (List<Contact>) selectSObjectsById(contactIds);
	}
}

The fflib_SObjectSelector Constructor Parameters and what each of them mean

When you create a Selector class that extends the fflib_SObjectSelector class you have the option to send some parameters to its constructor that determine how to the selector class functions. They are the following (in order of parameters passed to the constructor):

1) Would you like to allow your class to use field sets when building the initial query fields for your selector layer class? By default this parameter is set to false.

2) Would you like to enforce CRUD (Object level create, read, update, delete) security on your selector layer class? By default this parameter is set to true.

3) Would you like to enforce FLS (Field level security) on your selector layer class? By default this parameter is set to false.

4) Would you like your selected fields in your query to be sorted alphabetically when your query is created (this is literally just a sort call on a list of strings in the code)? By default this parameter is set to true.

If you would like to alter any of these settings for your selector class you can do the following:

public inherited sharing class Contact_Selector extends fflib_SObjectSelector
{
        //In our selector classes constructor we are calling the fflib_SObjectSelector using the super() call
        //and setting out parameters.
	public Contact_Selector(){
                //This is completely optional. If you like the defaults listed above you do not have to call the super class constructor at all.  
		super(false, true, true, false);
	}
}

Note that this is completely optional, if you like the default behavior listed above, just don’t bother calling the super method and overriding them!


How to set the default field selection for your Selector Class

One of the biggest benefits of the selector layer is selected field consistency in your queries. If 99% of the time you are querying for the subject field on your Case object, why not just query for it by default without ever thinking about it again right?? Well the getSObjectFieldList method that you implement in your Selector classes does just that. Here’s how to implement that method in your selector:

public List<Schema.SObjectField> getSObjectFieldList(){
        //Note that this is using concrete references to the fields, not dynamic soql (here at 
        //least). This is to ensure the system knows
        //your code is dependent on these fields so you don't accidentally delete them some 
        //day.
	return new List<Schema.SObjectField>{
                        //In this list, place every field you would like to be queried for by 
                        //default when creating a query
                        //with your selector class.
			Contact.Id,
			Contact.Name,
			Contact.FirstName,
			Contact.LastName
	};
}

If you choose to enable field sets to allow for default field selection for your selector class, you can implement the following method to select fields from the field set to be included in your queries:

public override List<Schema.FieldSet> getSObjectFieldSetList(){
    return new List<Schema.FieldSet>{SObjectType.Case.FieldSets.CaseFieldSetForSelector};
}

The major benefit of using the field sets for query fields is you can add new fields on the fly without adding extra code. This becomes super important if you’re building a managed package.


How to set your default OrderBy clause in your Selector Class

By default all Selector Layer Classes that extend the fflib_SObjectSelctor are ordered by the Name field (if the name field isn’t available on the queried object it defaults to CreatedDate). If that’s kewl with you, no need to override it, but if you’d prefer the default sort order for your select class be different then you just need to override the following method like so:

public override String getOrderBy(){
    return 'Subject';
}

If you wanted to order by multiple fields you would just do the following (basically just create a comma separated list in the form of a string):

public override String getOrderBy(){
    return 'Subject, Name, CustomField__c, CustomLookup__r.Name';
}

The fflib_QueryFactory class and Custom Queries

Chances are you’re gonna wanna query something that’s not immediately available via the fflib_SObjectSelect class, well lucky for you the fflib_QueryFactory class is here just for that! Here is an example of a custom query via the use of the fflib_QueryFactory class (a list of all available query factory methods are at the bottom of this wiki article).

//This allows us to select all new cases in the system using the QueryFactory in //fflib_SObjectSelector
public List<Case> selectNewCases(){
    return (List<Case>) Database.query(newQueryFactory().
    selectField(Case.Origin).
    setCondition('Status = \'New\'').
    setLimit(1000).
    toSOQL());
}

There are also tons of other methods that allow you to add offsets, subselects, set ordering and more (outlined in the method cheat sheet section).


How to Do Sub-Select Queries (Inner Queries)

There’s a kinda handy way to do sub-select queries by using the fflib_QueryFactory class. You can use it in your selector class’s methods as outlined below:

//Pretend this method exists in a Case_Selector class
public List<Case> innerQueryExample(){
    //Using this Case_Selectors newQueryFactory method that it inherits from the 
    //fflib_SObjectSelector class it extends
    fflib_QueryFactory caseQueryFactory = newQueryFactory();

    //Creating a new instance of our Task_Selector class and using the 
    //addQueryFactorySubselect method to add the task query as a 
    //inner query for the caseQueryFacorty
    fflib_QueryFactory taskSubSelectQuery = new 
    Task_Selector().addQueryFactorySubselect(caseQueryFactory);
  
    //Querying for our data and returning it.
    return (List<Case>) Database.query(caseQueryFactory.toSOQL());
}

How to do Aggregate Queries

There’s not really a built-in method in either the fflib_SObjectSelector or the QueryFactory class to deal with this. So you just deal with aggregate queries by building a method in your Selector Class in the following way:

public List<AggregateResult> selectAverageTacosPerTacoBell(){
    List<AggregateResult> tacoData = new List<AggregateResult>();
    for(AggregateResult result: [SELECT Id, AVG(Tacos_Sold__c) avgTacos FROM Taco_Bell__c 
        GROUP BY Taco_Type__c]){
        tacoData.add(result);
    }
    return tacoData;
}

The fflib_SObjectSelector Class methods Cheat Sheet

While there are many other methods within the fflib_SObjectSelector class below are the methods most commonly utilized in implementations.

1) getSObjectName()_ – Returns the name of the object that your select was built for.

2) selectSObjectsById(Set<Id> idSet) – Returns a query that selects all the records in your id set. It constructs a query based on the fields you declare in your selector class’s getSObjectFieldsList method and orders them by whatever is represented in the m_orderBy variable.

3) queryLocatorById(Set<Id> idSet) – This method is basically the same as the selectSObjectsById method except that it returns a query locator instead. This should be leveraged for batch classes that need query locators.

4) newQueryFactory – This method returns a new instance of the fflib_QueryFactory class and uses your selector classes fields listed in the getSObjectFieldsList method and orders them by whatever you set the default orderby to in your selector class.

5) addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory) – This method basically just creates a subselect query (an inner query) for the “parentQueryFactory” and then returns the parent query with a subselect query that represents the query for your objects selector class (more info on how this method works in the sub-select query section in this wiki article).


The fflib_QueryFactory Class methods Cheat Sheet

While there are many other methods within the fflib_QueryFactory class below are the methods most commonly utilized in implementations.

1) assertIsAccessible() – This method checks to see if the running user can actually read to object this selector was built for.

2) setEnforceFLS(Boolean enforce) – This method determines whether or not to enforce field level security on the query you are running.

3) setSortSelectFields(Boolean doSort) – If you would like the list of fields selected to be selected in alphabetical order, you can use this method to make your selected fields be selected in alphabetical order.

4) selectField(Schema.SObjectField field) – Use this method to select a field for your query.

5) selectFields(Set fields) – Use this method to select multiple fields for your query at the same time.

6) selectFieldSet(Schema.FieldSet fieldSet) – Use this method to select fields for your query from a field set.

7) setCondition(String conditionExpression) – Use this method to set the conditions for your query (basically you are setting the WHERE clause in your query. Do NOT add the WHERE to the string you pass into to this method).

8) setLimit(Integer limitCount) – Sets a limit for your query.

9) setOffset(Integer offsetCount) – Sets an offset for your query.

10) addOrdering(Ordering o) – Sets up an ORDER BY clause for your query. You need to build an fflib_QueryFactory.Ordering object to pass to this method. There are a ton of ordering method permutations in this class, so definitely check them all out.

11) subselectQuery(String relationshipName) – Sets up a subquery for the query. You need to pass in a string representation of the relationship fields developer name to this method.

12) toSOQL() – Takes the fflib_QueryFactory you’ve just built and turns it into an actual string representation of the query that you can use in a Database.query() call.

13) deepClone() – Creates a clone of your fflib_QueryBuilder query in case you’d like an easy way to generate another permutation of this query without rebuilding the whole thing.


Next Section

Part 15: The Difference Between Unit Tests and Integration Tests

SoC and the Apex Common Library Tutorial Series Part 13: The Selector Layer

What is the Selector Layer

The Selector Layer is Salesforce is based off Martin Fowler’s Data Mapper Layer concept. It’s, “a layer of Mappers that moves data between objects and a database while keeping them independent of each other and the Mapper itself”.

In most tech stacks when you want to represent records in a database table you create classes in your code base to represent them to hold them in memory and prep them for transit to the actual database. These are what Martin references as “objects” in the above quote. Salesforce already creates these classes for you in the background to represent your Custom and Standard Objects. It’s why you can just inherently write Case cs = new Case(); in Apex and it creates a brand new Case record for you.

Since Salesforce already does that work for you, the Data Mapper Layer, just turns into the Selector Layer and within the Selector Layer we are basically just concerned with housing and performing queries for our respective objects. You will ideally call upon the Selector Layer every single time you need to make a query in Apex. The largest goal with this layer is to avoid having repetitive queries everywhere within the system and to have some overall consistency with your object queries (the fields always queried, limits, order by clause, etc).


When to make a new Selector Layer Class

Whenever you need to create queries on an object you’ve never done queries on before, you would create a new Selector Layer Class. So for instance if you needed to create some queries for the case object to use in your service or domain layer classes, you would create a Case Selector class. There should typically be one selector class per object you intend to query on.


Selector Layer Naming Conventions

Class Names – Your classes should ideally follow the naming conventions of the domain layer just with Selector appended to the end of them, unless you have common cross object queries then it’s a bit different.

Selector Class Naming Examples (Note that I prefer underscores in names, this is personal preference):

Accounts_Selector
Opportunities_Selector
OpportunityQuotes_Selector

Method Naming and Signatures – The names of the methods in a selector class should all start with the word “select”. They should also only return a list, map or QuerySelector and should only accept bulkified parameters (Sets, Lists, Maps, etc). A few good examples of method examples are below.

Selector Method Examples

public List<sObject> selectById(Set<Id> sObjectIds)
public List<sObject> selectByAccountId(Set<Id> accountIds)
public Database.QueryLocator selectByLastModifiedDate(Date dateToFilterOn)

Selector Layer Security

The Selector Layer classes should all ideally inherit their sharing from the classes calling them. So they should typically be declared as follows:

public inherited sharing class Account_Selector

If there are queries for your object that you absolutely must have run in system context (without sharing) you would want to elevate those permissions through the use of a private inner class like so:

public inherited sharing class Account_Selector 
{
    public List<Account> selectAccountsById(Set<Id> acctIds){
        return new Account_Selector_WithoutSharing().selectAccountsByIdElevated(acctIds);
    } 

    private without sharing Account_Selector_WithoutSharing{
        public List<Account> selectAccountsByIdElevated(Set<Id> acctIds){
            return [SELECT Id FROM Account WHERE Id IN : acctIds]; 
        }
    }
}

Implementing the Selector Layer

To find out how to implement the Selector Layer using Apex Commons, continue reading here: Implementing the Selector Layer with the Apex Common Library . If you’re not interested in utilizing the Apex Common library for this layer there are pretty sparing options out there that are pre-built, the only other option I’m aware of at this time is Query.apex. Outside of that, you could certainly roll your own selector layer, but it is no small feat if done right.

Libraries That Could Be Used for the Domain Layer

Apex Common (Contains a framework for all layers)

Query.apex


Selector Layer Examples

Apex Common Examples (Suggested)

Case Object Selector Example (Lots of comments)

Contact Object Selector Example

Task Object Selector Example

Non Apex Common Examples

Case Object Selector Simple Example


Next Section

Part 14: Implementing the Selector Layer with the Apex Common Library

SoC and the Apex Common Library Tutorial Series Part 12: The Builder Pattern

What is the Builder Pattern?

The Builder Pattern is a Creational Design Pattern that allows you to construct a complex object one step at a time. Think about the construction of a car or your house or maybe something less complicated, like the construction of a desktop computer. When you’re creating a new desktop computer you have to make a ton of selections to build the computer. You have to get the right cpu, motherboard, etc. Instead of passing all that selection information into a class that constructed the computer, it’d be a lot nicer to build it step by step. Let’s check out some examples:

Non-Builder Pattern Computer Building Class Example:

public class ComputerBuilderController(){
    public ComputerCreator createMidTierComputer(){
        return new ComputerCreator(midTierGraphicsCard, midTierCPU, midTierMotherboard, 
        midTierFan, null, null).getComputer();
    }

    public ComputerCreator createTopTierComputer(){
        return new ComputerCreator(topTierGraphicsCard, topTierCPU, topTierMotherboard, 
        topTierFan, topTierNetworkCard, null).getComputer();
    }
}

public class ComputerCreator{
    private CPU compCPU;
    private GPU compGPU;
    private MotherBoard compMotherBoard;
    private Fan compFan;
    private NetworkCard compNetworkCard;
    private Speakers compSpeakers;

    //This could go on for forever and you might have 300 different constructors with 
    //different variations of computer parts... This could become
    //an absolutely enormous class.
    public ComputerCreator(GraphicsCard selectedGraphicsCard, CPU selectedCPU, MotherBoard 
          selectedMotherboard, Fan selectedFan, NetworkCard selectedNetworkCard, Speakers 
          selectedSpeakers){
        setComputer(selectedGraphicsCard, selectedCPU, selectedMotherboard, selectedFan, 
                    selectedNetworkCard, selectedSpeakers);
    }

    //Because of how this is setup, we're setting everything for the computer, even if we're 
    //just setting the computer parts to null
    private void setComputer(GraphicsCard selectedGraphicsCard, CPU selectedCPU, MotherBoard 
            selectedMotherboard, Fan selectedFan, NetworkCard selectedNetworkCard, Speakers 
            selectedSpeakers){
                    this.compGPU= selectedGraphicsCard;
                    this.compCPU = selectedCPU;
                    this.compMotherBoard = selectedMotherboard; 
                    this.compFan= selectedFan; 
                    this.compNetworkCard = selectedNetworkCard; 
                    this.compSpeakers = selectedSpeakers;   
    }

    public ComputerCreator getComputer(){
        return this;
    }
}

You can see in the above example, this setup is not exactly ideal, nor does it lend itself to easy code changes. If you go with the single constructor approach and just allow developers to pass in nulls to the constructor, every time you need to add another option for the computers your code might build, you’ll have to update every piece of code that calls the ComputerCreator class because the constructor will change. Alternatively if you go with new constructor variations for each new option you could end up with hundreds of constructors over time… also not great at all. That can be extremely confusing and difficult to upkeep. So let’s look at how to leverage the builder pattern to achieve the same thing.

Builder Pattern Computer Building Class Example:

public class ComputerBuilderController(){
       
    public ComputerCreator createMidTierComputer(){
        return new ComputerCreator().
                   setCPU(midTierCPU).
                   setGPU(midTierGPU).
                   setMotherBoard(midTierMotherBoard).
                   setFan(midTierFan);
    }

    public void createTopTierComputer(){
        return new ComputerCreator().
                   setCPU(topTierCPU).
                   setGPU(topTierGPU).
                   setMotherBoard(topTierMotherBoard).
                   setFan(topTierFan).
                   setNetworkCard(topTierNetworkCard);
    }
}

public class ComputerCreator{
    private CPU compCPU;
    private GPU compGPU;
    private MotherBoard compMotherBoard;
    private Fan compFan;
    private NetworkCard compNetworkCard;
    private Speakers compSpeakers;
    
    public ComputerCreator setCPU(CPU selectedCPU){
        this.compCPU = selectedCPU;
        return this;
    }

    public ComputerCreator setGPU(GPU selectedGPU){
        this.compGPU = selectedGPU;
        return this;
    }

    public ComputerCreator setMotherBoard(MotherBoard selectedMotherBoard){
        this.compMotherBoard = selectedMotherBoard;
        return this;
    }

    public ComputerCreator setFan(Fan selectedFan){
        this.compFan = selectedFan;
        return this;
    }

    public ComputerCreator setNetworkCard(NetworkCard selectedNetworkCard){
        this.compNetworkCard = selectedNetworkCard;
        return this;
    }

    public ComputerCreator setSpeakers(Speaker selectedSpeakers){
        this.compSpeakers= selectedSpeakers;
        return this;
    }
}

You can see in the above example that using the builder pattern here gives us an enormous amount of flexibility. We no longer need to pass null values into a constructor or build a bajillion constructor variations, we only need to call the methods to set each piece of the computer should we need to set them. You can see we now only worry about setting values for things we actually need to set for our computer. Additionally, you can add new options for computer parts to set in the ComputerCreator class easily and it won’t affect that code that has already been written. For instance if I created a setWebcam method it would be no big deal. My createMidTierComputer and createTopTierComputer methods would not be impacted in any way and continue to function just fine. Builder Pattern FTW!


Why is it Useful?

Take the computer example above, without the builder pattern you get one of two things. You either get an enormous constructor you send all your computer parts to (that you will likely pass a ton of nulls to) or you have a ton of constructors to represent different computer variations… either choice is not a great choice. Complex objects typically have potentially hundreds of optional choices you can make, you need something more robust to select those options.

The builder pattern allows you to select those options piece by piece if you want them. Take for instance the computer example again. Desktop computers do not need things like network cards or speakers or a webcam to function. That being said, many people building a computer may want them for one reason or another to make their specific computer useful for them. Instead making constructor variations for every combination of those items, why not just use the builder pattern to add them as needed? It makes the code a whole lot easier to deal with and easier to extend in the future.


Where does it fit into Separation of Concerns?

Builder classes are typically service classes of some sort, maybe you create some super elaborate Opportunities in your org. You might have an Opportunity_Builder_Service or something along those lines. It can help in a lot of areas to reduce your code in the long term and to increase your codes flexibility for allowing new options for the object you are building, and I think we all know (if you’ve been doing this long enough), businesses like to add and subtract things from the services they create on a whim.


Where is it used in the Apex Common Library?

This design pattern is leveraged heavily by the fflib_QueryFactory class in the Apex Common Library. It allows us to build complex SOQL queries by building them step by step.


Example Code

The fflib_QueryFactory class is an example of a class designed using the builder pattern.

The Case_Selector class I’ve created has several examples of how it looks when you call and utilize a class leveraging the builder pattern.


Next Section

Part 13: The Selector Layer

SoC and the Apex Common Library Tutorial Series Part 11: Implementing The Domain Layer with the Apex Common Library

The template for every Domain Class you create

Every Domain layer class you create for an object should at minimum have the following logic in it for it to work as expected.

//All domain classes should utilize inherited sharing so that the caller determines whether it //should operate in system context or not. The should
//also extend the fflib_SObjectDomain class
public inherited sharing class Cases extends fflib_SObjectDomain{
    
    //The constructor should always accept a list of the SObject type we're creating the 
    //domain class for
    //It should then pass this list to the fflib_SObjectDomain class's constructor which is 
    //what super(cases) does.
    //This sets the records value in the fflib_SObjectDomain class which is very important 
    public Cases(List<Case> cases){
        super(cases);
    }

    //The name of this inner class must always be Constructor to work appropriately. This acts 
    //as a way to use the concept of reflection when initializing
    //this class, despite the fact apex still does not support it.
    public class Constructor implements fflib_SObjectDomain.IConstructable {
        public fflib_SObjectDomain construct(List<SObject> sObjectList) {
            return new Cases(sObjectList);
        }
    }
}

To understand why the Constructor inner class is necessary in these classes check out the triggerHandler method in the fflib_SObjectDomain class here: fflib_SObjectDomain triggerHandler method


Trigger Implementations using the Apex Common Library’s Domain Layer

If you didn’t know already, triggers should ideally have no logic in them… ever. Thankfully this concept has also been built into the Apex Common Library. To call the Domain Layer class you have built for your object in your trigger, just do the following:

//Note that I like to use the _Trigger in my trigger names, this is just personal preference //as it makes it easier to discern it's a trigger
trigger NameOfDomainLayerClass_Trigger on YourObject (before insert, before update, after insert, after update)
{
    //This trigger handler method eventually calls the Construct inner class of your Domain 
    //class to construct a version of your class
    //and implement the logic in it
    fflib_SObjectDomain.triggerHandler(NameOfDomainLayerClass.class);
}

How to Access the Trigger variables in your Domain Class

Technically, you could leverage trigger.new, trigger.oldMap etc in your domain class… however you shouldn’t for two reasons. The first reason is you will likely (at some point) want to call some aspects of your Domain class from outside a trigger context. If your Domain relies on the trigger context to operate, that’s less than ideal. The second reason is you can’t mock the trigger context, so a ton of benefit of setting up these separation of concerns will be lost. Short story, never access trigger context variables directly in your domain class.

Now you might be wondering, “This Domain class is supposed to be able to run in trigger context… I need to access those variables!!”. No worries, you can still access them when you need them. If you’ve worked in SF long enough, with time you start to learn the only trigger context variables you need access to are trigger.new and trigger.oldMap. The rest typically really shouldn’t be used. Trust me… you don’t need them.

So how do you actually get access to trigger.oldMap and trigger.new? Well that requires us to take a closer look at the triggerHandler method in the fflib_SObjectDomain class that our actual triggers call (example just above this section).

Basically when our trigger calls that triggerHandler method, it eventually runs the code below (source code here):

 if(isInsert) domainObject = domainConstructor.construct(newRecords);
 else if(isUpdate) domainObject = domainConstructor.construct(newRecords);
 else if(isDelete) domainObject = domainConstructor.construct(oldRecordsMap.values());
 else if(isUndelete) domainObject = domainConstructor.construct(newRecords);

The code above essentially passes trigger.new to the Records variable in the fflib_SObjectDomain class you Domain class extends when you are doing and insert, update or undelete operation; and it passes in trigger.oldMap.values to the Records variable if you are doing a delete operation.

Ok that’s cool, but how do you access trigger.oldMap when you need it?? Well, the only time you need trigger.oldMap are in update operations, so that’s the only time it’s accessible. When you setup your onBeforeUpdate or onAfterUpdate methods in your Domain class you’ll set them up like what you see below:

public override void onBeforeUpdate(Map<Id, SObject> existingRecords){
    //existingRecords is trigger.oldMap
} 

In trigger context when onBeforeUpdate gets called, trigger.oldMap is passed in to the existingRecords variable and you’re free to use it as you please.

There you have it! That’s it! Simpler than you maybe thought… maybe, lol.


The fflib_SObject Domain Class methods Cheat Sheet

While there are many other accessible methods in the fflib_SObjectDomain class below are the methods most commonly utilized in implementations.

1) onApplyDefaults() This method is called in the handleBeforeInsert method and exists so that you can apply default logic that is applicable to all new records that are created in the system.
2) onValidate() This method is called in the handleAfterInsert method and exists so that you can apply validation logic to your inserted records before commiting them to the database.
3) onValidate(Map<Id, SObject> existingRecords) This method is called in the handleAfterUpdate method and exists so that you can apply validation logic to your updated records before commiting them to the database.
4) onBeforeInsert() This method is called in the handleBeforeInsert method and exists so that you can override it to place logic that should occur during a before insert action in a trigger.
5) onBeforeUpdate(Map<Id, SObject>) This method is called in the handleBeforeUpdate method and exists so that you can override it to place logic that should occur during a before update action in a trigger.
6) onBeforeDelete() This method is called in the handleBeforeDelete method and exists so that you can override it to place logic that should occur during a before delete action in a trigger.
7) onAfterInsert() This method is called in the handleAfterInsert method and exists so that you can override it to place logic that should occur during an after insert action in a trigger.
8) onAfterUpdate(Map<Id, SObject>) This method is called in the handleAfterUpdate method and exists so that you can override it to place logic that should occur during an after update action in a trigger.
9) onAfterDelete() This method is called in the handleAfterDelete method and exists so that you can override it to place logic that should occur during an after delete action in a trigger.
10) onAfterUndelete() This method is called in the handleAfterUndelete method and exists so that you can override it to place logic that should occur during an after undelete action in a trigger.
11) handleBeforeInsert() This method is called in the triggerHandler method when a beforeInsert is happening in the trigger. By default it calls the onApplyDefaults method and the onBeforeInsert method but it can be overridden and implemented in a different way if desired.
12) handleBeforeUpdate(Map<Id, SObject>) This method is called in the triggerHandler method when a beforeUpdate is happening in the trigger. By default it calls the onBeforeUpdate method but it can be overridden and implemented in a different way if desired.
13) handleBeforeDelete() This method is called in the triggerHandler method when a beforeDelete is happening in the trigger. By default it calls the onBeforeDelete method but it can be overridden and implemented in a different way if desired.
14) handleAfterInsert() This method is called in the triggerHandler method when an afterInsert is happening in the trigger. By default it calls the onValidate and onAfterInsert method but it can be overridden and implemented in a different way if desired.
15) handleAfterUpdate() This method is called in the triggerHandler method when an afterUpdate is happening in the trigger. By default it calls the onValidate and onAfterUpdate method but it can be overridden and implemented in a different way if desired.
16) handleAfterDelete() This method is called in the triggerHandler method when an afterDelete is happening in the trigger. By default it calls the onAfterDelete method but it can be overridden and implemented in a different way if desired.
17) handleAfterUndelete() This method is called in the triggerHandler method when an afterUndelete is happening in the trigger. By default it calls the onUndelete method but it can be overridden and implemented in a different way if desired.
18) getChangedRecords(Set<String> fieldNames) This method will return a list of records that have had their fields changed (the fields specificied in the method parameter passed in).
19) getChangedRecords(Set<Schema.SObjectField> fieldTokens) This method will return a list of records that have had their fields changed (the fields specificied in the method parameter passed in). I would suggest using this method over the one above. Strongly typed field names are a better choice in my opinion so the system knows your code depends on that field.


The Configuration Inner Class for fflib_SObjectDomain (Setting trigger state and trigger security)

Inside the fflib_SObjectDomain class you’ll find an inner class called Configuration. This inner class allows you to enable and disable Trigger State as well as enable and disable CRUD security in your trigger. By default trigger state is disabled and CRUD security is enabled.

Trigger State

The trigger state parameter allows you to choose to use the same instance of your Domain class between the before and after portion of the trigger. It needs to be used carefully as this could cause trigger recursion if not implemented properly.

How to turn trigger state on and off using the Configuration inner class:

//Turn on
Configuration.enableTriggerState();
//Turn off
Configuration.disableTriggerState();

Enforcing CRUD

The enforcing trigger CRUD (Create, Read, Update, Delete) ensures that a users has the appropriate object CRUD permissions before performing any actual DML actions. By default in the fflib_SObjectDomain class this is enforced. Ideally you should leave this as enforced unless you have a really excellent business reason to not enforce it.

How to turn CRUD enforcement on and off using the Configuration inner class:

//Enable CRUD
Configuration.enforceTriggerCRUDSecurity();
//Disable CRUD
Configuration.disableTriggerCRUDSecurity();

The Trigger Event Inner Class (Turning trigger events on and off)

Inside the fflib_SObjectDomain class is an inner class called TriggerEvent that allows you to turn on and off the various trigger events at will. By default all trigger events are turned on.

Example Code for shutting down and re-enabling a portion of a domain trigger

//Disables to before insert portion of the trigger
DomainClassName.getTriggerEvent(DomainClassName.class).disableBeforeInsert();
//Code to execute
//Enables the before insert portion of the trigger
DomainClassName.getTriggerEvent(DomainClassName.class).enableBeforeInsert();

The following is a list of trigger event methods a what they do:

1) TriggerEvent.enableBeforeInsert() This method enables the before insert portion of the trigger.

2) TriggerEvent.enableBeforeUpdate() This method enables the before update portion of the trigger.

3) TriggerEvent.enableBeforeDelete() This method enables the before delete portion of the trigger.

4) TriggerEvent.disableBeforeInsert() This method disables the before insert portion of the trigger.

5) TriggerEvent.disableBeforeUpdate() This method disables the before update portion of the trigger.

6) TriggerEvent.disableBeforeDelete() This method disables the before delete portion of the trigger.

7) TriggerEvent.enableAfterInsert() This method enables the after insert portion of the trigger.

8) TriggerEvent.enableAfterUpdate() This method enables the after update portion of the trigger.

9) TriggerEvent.enableAfterDelete() This method enables the after delete portion of the trigger.

10) TriggerEvent.enableAfterUndelete() This method enables the after undelete portion of the trigger.

11) TriggerEvent.disableAfterInsert() This method disables the after insert portion of the trigger.

12) TriggerEvent.disableAfterUpdate() This method disables the after update portion of the trigger.

13) TriggerEvent.disableAfterDelete() This method disables the after delete portion of the trigger.

14) TriggerEvent.disableAfterUndelete() This method disables the after undelete portion of the trigger.

15) TriggerEvent.enableAll() This method enables all portions of the trigger.

16) TriggerEvent.disableAll() This method disables all portions of the trigger.

17) TriggerEvent.enableAllBefore() This method enables all before portions of the trigger.

18) TriggerEvent.disableAllBefore() This method disables all before portions of the trigger.

19) TriggerEvent.enableAllAfter() This method enables all after portions of the trigger.

20) TriggerEvent.disableAllAfter() This method disables all after portions of the trigger.


Example Apex Common Implementation of a Domain Class

Cases Domain Layer Example

Contacts Domain Layer Example


Next Section

Part 12: The Builder Pattern

SoC and the Apex Common Library Tutorial Series Part 10: The Domain Layer

What is the Domain Layer?

The Domain Layer is, “An object model of the domain that incorporates both behavior and data”. – Martin Fowler

In most coding languages you need to connect to the database, query for the data and then you create wrapper classes to represent each underlying table in your database(s) to allow you to define how that particular table (object) should behave. Salesforce, however, already does a lot of this for you, for instance there is no need to connect to a Database, declarative behavior for you tables (objects) are already represented and your tables (objects) already have wrapper classes pre-defined for them (Ex: Contact cont = new Contact()).

However the logic represented in a trigger is an exception to this rule. Apex triggers represent a unique scenario on the Salesforce platform, they are necessary for complex logic, but inherently they do not abide by any object oriented principles. You can’t create public methods in them, you can’t unit test them, you can’t re-use logic placed directly in a trigger anywhere else in your system, etc. Which is a massive detriment we need to overcome. That’s where the domain layer comes in to play.

The Domain Layer will allow you on an object by object basis have an object oriented approach to centralize your logic. Basically, logic specific to a single object will be located in one place and only one place by using the domain layer. This ensures your logic specific to a single object isn’t split into a ton of different places across your org.


When to make a new Domain Layer Class

Basically, at the very least, anytime you need to make a trigger on an object you should implement a Domain Class. However this is a bit generalized, sometimes you don’t actually need a trigger on an object, but you have object specific behavior that should be implemented in a Domain class. For instance, if you have an object that doesn’t need a trigger, but it has a very specific way it should have its tasks created, you should probably create a Domain Layer class for that object and put that task creation behavior there.

A domain layer class is essentially a mixture of a trigger handler class and a class that represents object specific behaviors.


Where should you leverage the domain layer in your code?

You should only ever call to the domain layer code from service class methods or from other domain class methods. Controller, Batch Classes, etc should never call out to the domain directly.


Domain Class Naming Conventions

Class Names – Domain classes should be named as the plural of whatever object you are creating a domain layer for. For instance if you were creating a domain layer class for the Case object, the class would be declared as follows: public inherited sharing class Cases. This indicates that the class should be bulkified and handles multiple records, not a single object record.

Class Constructor – The constructor of these classes should always accept a list of records. This list of records will be leveraged by all of the methods within the domain class. This will be further explained below.

Method Names – Method names for database transaction should use the onTransactionName naming convention (Example: onAfterInsert). If the method is not related to a database transaction it should descriptive to indicate what domain logic is being executed within it (Example: determineCaseStatus).

Parameter Names and Types – You do not typically need to pass anything into your domain layer methods. They should primarily operate on the list of records passed in the constructor in the majority of situations. However some behavior based (non-trigger invoked) methods may need other domain objects and/or units of work passed to them. This will be further explained in the sections below.


Domain Layer Best Practices

Trasnaction Management

In the event you are actually performing DML operations in your Domain class, you should either create a Unit of Work or have one passed into the method doing the DML to appropriately manage your transaction. In the event you are not wanting to leverage the unit of work pattern you should make sure to at the very least set your System.Savepoint savePoint = Database.setSavePoint(); prior to doing your DML statement and use a try catch block to rollback if the DML fails.


Implementing the Domain Layer

To find out how to implement the Domain Layer using Apex Common, continue reading here: Implementing the Domain Layer with the Apex Common Library. If you’re not interested in utilizing the Apex Common library for this layer you can implement really any trigger framework and the core of the domain layer will be covered.

Libraries That Could Be Used for the Domain Layer

Apex Common (Contains a framework for all layers)

Apex Trigger Actions Framework

SFDC Trigger Framework

MyTriggers


Domain Layer Examples

Apex Common Examples (Suggested)

Case Object Domain Layer Example

Contact Object Domain Layer Example

SFDC Trigger Framework Example

Case Object Domain Layer Example


Next Section

Part 11: Implementing the Domain Layer with the Apex Common Library

SoC and the Apex Common Library Tutorial Series Part 9: The Template Method Pattern

What is the Template Method Pattern?

The Template Method Pattern is one of the more popular Behavioral Design Pattern. The Template Design Pattern basically is creating a genericized skeleton class that a sub class can extend and add functionality to. The genericized skeleton class has some core functionality pre-built, but expects you to fill out (although not explicitly) other overridable methods in your sub class, to actually get much benefit out of it. Most trigger frameworks in existence leverage the Template Method Pattern. In fact there are a lot of frameworks in existence out there that leverage this pattern and I’m not even sure the creators know they leveraged it.


Why is it Useful?

This pattern is extremely useful because it allows you to define the core, generic parts of a class implementation (so it doesn’t need to be re-built over and over), while also allowing different developers the ability to implement their unique logic for their specific implementation. Take for instance a simple trigger handler framework. Most of these use the template method pattern. The core functionality is there (when to run a before insert method or how to handle certain trigger context variables, etc) but the object specific logic methods are overridable. For instance, the methods that determine what to do on the insert of a record, that would be overridden in an extended sub class and then on an object by object basis that logic would be able to differ.


Where does it fit into Separation of Concerns?

This fits into the concept of SoC because this pattern makes sure that you don’t repeat yourself (the DRY principle) and you write the minimal amount of code. Basically it allows you to separate out the generic code from the object specific code that has to be executed. You only write the generic code once and then allow subclasses to extend your template class and implement logic for those empty methods in your template class that need to have object or service specific logic.


Where is it used in the Apex Common Library

This design pattern is leveraged heavily by the fflib_SObjectDomain class in the Apex Common Library.


Example Code (Abstract Task Creation App)

fflib_SObjectDomain class – This class in the Apex Common library uses the template method pattern. Observe the many empty overridable methods (onBeforeInsert, onValidate, onBeforeUpdate, etc). It is expecting that a subclass will extend it and override one or more of those methods to make any true functionality occur.

Cases domain class that extends the fflib_SObjectDomain Template Class – The methods onApplyDefaults and onValidate are empty methods in the template class (the fflib_SObjectDomain class) that you need to implement in your subclasses to have any functionality happen.


Next Section

Part 10: The Domain Layer

SoC and the Apex Common Library Tutorial Series Part 8: Implementing the Service Layer with the Apex Common Library

Preparation for the rest of this article

There is NO FRAMEWORK that can be made for service layer classes. This is a business logic layer and it will differ everywhere. No two businesses are identical. That being said, if you would like to leverage all of the other benefits of the Apex Common Library (primarily Apex Mocks) and you would like your service classes to be able to leverage the fflib_Application class to allow for dynamic runtime logic generation, you’ll need to structure your classes as outlined below. If you don’t want to leverage these things, then don’t worry about doing what is listed below… but trust me, in the long run it will likely be worth it as your org grows in size.


The Service Interface

For every service layer class you create you will create an interface (or potentially a virtual class you can extend) that your service layer implementation class will implement (more on that below). This interface will have every method in your class represented in it. An example of a service interface is below. Some people like to prefix their interfaces with the letter I (example: ICaseService), however I prefer to postfix it with _I or _Interface as it’s a bit clearer in my opinion.

This methods in this interface should represent all of the public methods you plan to create for this service class. Private methods should not be represented here.

public interface Task_Service_Interface
{
	void createTasks(Set<Id> recordIds, Schema.SObjectType objectType);
}

The Service Layer Class

This class is where things get a little confusing in my opinion, but here’s the gist of it. This is the class you will actually call in your apex controllers (or occasionally domain classes) to actually execute the code… however there are no real implementation details in it (that exists in the implementation class outlined below). The reason this class sits in as a kind of middle man is because we want, no matter what business logic is actually called at run time, for our controller classes, batch classes, domain classes, etc to not need to alter the class they call to get the work done. In the Service Factory section below we’ll see how that becomes a huge factor. Below is an example of the Service Layer class setup.

//This class is what every calling class will actually call to. For more information on the //Application class check out the fflib_Application class
//part of this wiki.
public with sharing class Task_Service
{
	//This literally just calls the Task_Service_Impl class's createTasks method
	global static void createTasks(Set<Id> recordIds, Schema.SObjectType objectType){
		service().createTasks(recordIds, objectType);
	}

	//This gets an instance of the Task_Service_Impl class from our Application class. 
        //This method exists for ease of use in the other methods 
        //in this class
	private static Task_Service_Interface service(){
            return (Task_Service_Interface) 
                   Application.service.newInstance(Task_Service_Interface.class);
	}
}

The Service Implementation Class

This is the concrete business logic implementation. This is effectively the code that isn’t super abstract, but is the more custom built business logic specific to the specific business (or business unit) that needs it to be executed. Basically, this is where your actual business logic should reside. Now, again, you may be asking, but Matt… why not just create a new instance of this class and just use it? Why create some silly interface and some middle man class to call this class. This isn’t gonna be superrrrrrr simple to wrap your head around, but bear with me. In the next section we tie all these classes together and paint the bigger picture. An example of a Service Implementation class is below.

/**
 * @description This is the true implementation of your business logic for your service layer. 
    These impl classes
 * are where all the magic happens. In this case this is a service class that executes the 
   business logic for Abstract
 * Task creation on any theoretical object.
 */

public with sharing class Task_Service_Impl implements Task_Service_Interface
{
	//This method creates tasks and MUST BE IMPLEMENTED since we are implementing the 
        //Task_Service_Interface
	public void createTasks(Set<Id> recordIds, Schema.SObjectType objectType)
	{
		//Getting a new instance of a domain class based purely on the ids of our 
                //records, if these were case
		//ids it would return a Case object domain class, if they were contacts it 
                //would return a contact
		//object domain class
		fflib_ISObjectDomain objectDomain = Application.domain.newInstance(recordIds);

		//Getting a new instance of our selector class based purely on the object type 
                //passed. If we passed in a case
		//object type we would get a case selector, a contact object type a contact 
                //selector, etc.
		fflib_ISObjectSelector objectSelector = 
                Application.selector.newInstance(objectType);

		//We're creating a new unit of work instance from our Application class.
		fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance();

		//List to hold our records that need tasks created for them
		List<SObject> objectsThatNeedTasks = new List<SObject>();

		//If our selector class is an instance of Task_Selector_Interface (if it 
                //implement the Task_Selector_Interface
		//interface) call the selectRecordsForTasks() method in the class. Otherwise 
                //just call the selectSObjectsById method
		if(objectSelector instanceof  Task_Selector_Interface){
			Task_Selector_Interface taskFieldSelector = 
                        (Task_Selector_Interface)objectSelector;
			objectsThatNeedTasks = taskFieldSelector.selectRecordsForTasks();
		}
		else{
			objectsThatNeedTasks = objectSelector.selectSObjectsById(recordIds);
		}

		//If our domain class is an instance of the Task_Creator_Interface (or 
                //implements the Task_Creator_Interface class)
		//call the createTasks method
		if(objectDomain instanceof Task_Creator_Interface){
			Task_Creator_Interface taskCreator = 
                        (Task_Creator_Interface)objectDomain;
			taskCreator.createTasks(objectsThatNeedTasks, unitOfWork);
		}

		//Try commiting the records we've created and/or updated in our unit of work 
                //(we're basically doing all our DML at
		//once here), else throw an exception.
		try{
			unitOfWork.commitWork();
		}
		catch(Exception e){
			throw e;
		}
	}
}

The fflib_Application.ServiceFactory class

The fflib_Application.ServiceFactory class… what is it and how does it fit in here. Well, if you read through all of Part 4: The fflib_Application Class then you hopefully have some solid background on what it’s used for and why, but it’s a little trickier to conceptualize for the service class so let’s go over it a bit again. Basically it leverages The Factory Pattern to dynamically generate the correct code implementations at run time (when your code is actually running).

This is awesome for tons of stuff, but it’s especially awesome for the service layer. Why? You’ll notice as your Salesforce instance grows so do the amount of interested parties. All of the sudden you’ve gone from one or two business units to 25 different business units and what happens when those businesses need the same type of functionality with differing logic? You could make tons of if else statements determining what the user type is and then calling different methods based on that users type… but maybe there’s an easier way. If you are an ISV (a managed package provider) what I’m about to show you is likely 1000 times more important for you. If your product grows and people start adopting it, you absolutely need a way to allow flexibility in your applications business logic, maybe even allow them to write their own logic and have a way for your code to execute it??

Let’s check out how allllllllllll these pieces come together below.


Tying all the classes together

Alright, let’s tie everything together piece by piece. Pretend we’ve got a custom metadata type that maps our service interfaces to a service class implementation and a custom user permission (or if you don’t wanna pretend you can check it out here). Let’s first start by creating our new class that extends the fflibApplication.ServiceFactory class and overrides its newInstance method.

/*
   @description: This class is an override for the prebuilt fflib_Application.ServiceFactory 
   that allows
   us to dynamically call service classes based on the running users custom permissions.
 */

public with sharing class ServiceFactory extends fflib_Application.ServiceFactory
{
	Map<String, Service_By_User_Type__mdt> servicesByUserPermAndInterface = new 
        Map<String, Service_By_User_Type__mdt>();

	public ServiceFactory(Map<Type, Type> serviceInterfaceByServiceImpl){
		super(serviceInterfaceByServiceImpl);
		this.servicesByUserPermAndInterface = getServicesByUserPermAndInterface();
	}

	//Overriding the fflib_Application.ServiceFactory newInstance method to allow us to 
        //initialize a new service implementation type based on the 
        //running users custom permissions and the interface name passed in.
	public override Object newInstance(Type serviceInterfaceType){
		for(Service_By_User_Type__mdt serviceByUser: 
                servicesByUserPermAndInterface.values()){
			 
                if(servicesByUserPermAndInterface.containsKey(serviceByUser.User_Permission__c 
                  + serviceInterfaceType)){
			 Service_By_User_Type__mdt overrideClass = 
                         servicesByUserPermAndInterface.get(serviceByUser.User_Permission__c + 
                         serviceInterfaceType.getName());
		         return 
                    Type.forName(overrideClass.Service_Implementation_Class__c).newInstance();
			}
		}
		return super.newInstance(serviceInterfaceType);
	}

	//Creating our map of overrides by our user custom permissions
	private Map<String, Service_By_User_Type__mdt> getServicesByUserPermAndInterface(){
		Map<String, Service_By_User_Type__mdt> servicesByUserType = 
                new Map<String, Service_By_User_Type__mdt>();
		for(Service_By_User_Type__mdt serviceByUser: 
                Service_By_User_Type__mdt.getAll().values()){
			//Checking to see if running user has any of the permissions for our 
                        //overrides, if so we put the overrides in a map
			 
         if(FeatureManagement.checkPermission(serviceByUser.User_Permission__c)){
			servicesByUserType.put(serviceByUser.User_Permission__c + 
                        serviceByUser.Service_Interface__c, serviceByUser);
			}
		}
		return servicesByUserType;
	}
}

Cool kewl cool, now that we have our custom ServiceFactory built to manage our overrides based on the running users custom permissions, we can leverage it in the Application Factory class we’ve hopefully built by now like so:

public with sharing class Application
{
       //Domain, Selector and UOW factories have been omitted for brevity, but should be added 
       //to this class

	//This allows us to create a factory for instantiating service classes. You send it 
        //the interface for your service class
	//and it will return the correct service layer class  
        //Exmaple initialization: Object objectService = 
        //Application.service.newInstance(Task_Service_Interface.class);
	public static final fflib_Application.ServiceFactory service =
                  new ServiceFactory(
                    new Map<Type, Type>{Task_Service_Interface.class => 
                                        Task_Service_Impl.class});
}

Ok we’ve done the hardest parts now. Next we need to pretend that we are using the service class interface, service implementation class and service class that we already built earlier (just above you, scroll up to those sections and review them if you forgot), because we’ve about to see how a controller would call this task service we’ve built.

public with sharing class Abstract_Task_Creator_Controller
{
	@AuraEnabled
	public static void createTasks(Id recordId){
		Set<Id> recordIds = new Set<Id>{recordId};
		Schema.SObjectType objectType = recordId.getSobjectType();
		try{
			Task_Service.createTasks(recordIds, objectType);
		}
		catch(Exception e){
			throw new AuraHandledException(e.getMessage());
		}
	}
}

Now you might be wracking your brain right now and being like… ok, so what… but look closer Simba. This controller will literally never grow, neither will your Application class or your ServiceFactory class we’ve built above (well the Application class might, but very little). This Task_Service middle man layer is so abstract you can swap out service implementations on the fly whenever you want and this controller will NEVER NEED TO BE UPDATED (at least not for task service logic)! Basically the only thing that will change at this point is your custom metadata type (object), the custom permissions you map to users and you’ll add more variations of the Task Service Implementation classes throughout time for your various business units that get onboarded and want to use it. However, your controllers (and other places in the code that call the service) will never know the difference. Wyld right. If you’re lost right now lets follow the chain of events step by step in order to clarify some things:

1) Controller calls the Task_Service class’s (the middleman) createTasks() method.
2) Task_Service’s createTasks() method calls its service() method.
3) The service() method uses the Application classes “service” variable, which is an instance of our custom ServiceFactory class (shown above) to create a new instance of our whatever Task Implementation class (which inherits from the Task_Service_Interface class making it of type Task_Service_Interface) is relevant for our users assigned custom permissions by using the newInstance() method the ServiceFactory class overrode.
4) The service variable returns the correct Task Service Implementation for the running user.
5) The createTasks() method is called for whatever Task Service Implementation was determined to be correct for the running user.
6) Tasks are created!

If you’re still shook by all this, please, watch the video where we build all this together step by step and walk through everything. I promise, even if it’s a bit confusing, it’s worth the time to learn.


Next Section

Part 9: The Template Method Pattern