When you first start learning about software development, I’d recommend against beginning with design patterns. Why? If you start with design patterns, you might be misled and start thinking that all of your code must conform to a design pattern, which isn’t the case and makes the process of learning how to code even more complicated. You’ll end up confused and overwhelmed, and your code could end up overengineered and wonky.
Instead, I encourage you to start with the basic building blocks of code, and design a few applications without using any design patterns, and that can serve as a foundation for more advanced functions, such as design patterns, later on. After you’ve mastered the basics of coding, and experienced a handful of difficult development situations, you’ll be ready to go back and learn about design patterns, and use them to solve tricky and difficult problems or situations in the code you develop.
Also, I recommend you learn more about design principles before getting into design patterns since those principles guide the design patterns. Design patterns will make much more sense once you’ve got a handle on the underlying design principles. To learn more about design principles, you can also check out the book Clean Codeby Robert Martin, a fantastic resource for any budding code writer.
What Are Design Patterns?
Once you’re comfortable with the basics of coding and design principles, it’s time for the third step: understanding design patterns! True to their name, design patterns are coding patterns that can help you fix tricky situations you’ll find yourself in while coding, but that’s just the start. Design patterns can also make your code more flexible and easier to read, and be more performant when you’re done writing it.
Suppose you wrote something, and it always takes 2-3 minutes to load. You might be able to use the Singleton pattern to only load something that is very time-consuming once, which will likely cut down on the page-load time. And that’s just one example. Design patterns use their patterns to fix practically any problem or mess you’ve got in your software, and certain design patterns can be prescribed for certain coding issues.
You can think of them as medicine for your code, such as a doctor prescribing either Advil, Tylenol, or Ibuprofin for your headache. Any three of those would work 90% of the time for your headache, and in the other 10%, you may need to try something else. It’s the same with design patterns; none of them is a guaranteed miracle fix for a coding issue, but they generally work, and a skilled developer can prescribe one for a development problem.
Which Design Patterns Should You Learn?
Make no bones about it: there are a lot of design patterns out there! I couldn’t possibly list them all. For now, though, we can narrow the field down to 23 particular design patterns that are best learned first, and they are widely used, too (and they’re well-regarded, too). They are described as the “gang of four” design patterns since they were designed by a quartet of people calling themselves the gang of four. They even wrote a book together on this topic titled Design Patterns: Elements of Reusable Object-Oriented Software. You can check it out to get plenty of in-depth information.
These 23 design patterns are sorted into three categories: behavioral design patterns, creational design patterns, and structural design patterns. These include design patterns that you’ve probably heard of before, such as the Singleton pattern or the Observer pattern. Remarkably, these design patterns are almost 30 years old, but are still in use today, proving just how well-designed and universal in usage they are.
Later in my series, we will review all 23 of those design patterns and how to implement them in your own code. We will also go over some basic areas of object-oriented programming, just in case you’re not familiar with that topic, along with inheritance, encapsulation, and polymorphism.
That’s all for now. I hope that in the future, you’ll master all 23 design patterns and put them to work in your own development tasks and see for yourself just how handy they can really be! Until next time!
Get Coding With The Force Merch!!
We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Let’s review what an IDE is and why it’s so incredibly helpful to you as a developer in Salesforce and beyond. As a developer, you’re encouraged to use an IDE, since it can make your work so much easier.
An IDE is an integrated development environment, where you can combine a wide variety of development tools to do your work much faster and more efficiently every day. Now, let’s check out an example (below) of an IDE at work. This particular IDE is IntelliJ, and I’m using a plug-in that allows me to do Salesforce development called the Illuminated Cloud 2 plug-in.
Demoing the Benefits of Using an IDE
An IDE like IntelliJ here will make your life, and the lives of your developer teammates, so much easier. In this interface, I have my code editor so I can write Apex code or a lightning web component, among other things. I can also analyze debug logs here in this IDE, or even run anonymous Apex. But why should you use an IDE and not just a developer console? An IDE like IntelliJ has many features that developer consoles don’t.
The first major benefit is if you want to know everywhere that a class is used in your codebase, you can simply copy the name of the class, then press CTRL-shift-F, and then the IDE searches for the class in all of the code in your Salesforce environment. There are also a litany of other hotkeys that will make traversal through your code base considerably easier. Shortcuts like that aren’t available in the developer console.
Autocomplete is another major advantage in using an IDE like IntelliJ with Illuminated Cloud 2. You can type “system.” and the IDE knows methods are available for that system class in the Apex language. So, you it will present to you a list of autocompleted methods that you can select from and have your code auto-completed for you. By contrast, the Salesforce developer console’s auto-complete features struggle and sometimes just outright do not work. This makes it easy for programmers, like you, to know all your options without having to look them up elsewhere in documentation.
There’s even more an IDE can do for you. For example, you can enable version control, allowing you to create local backups of your code, so you can revert back if something goes wrong. You sure can’t do that in a developer console! Meanwhile, you can find more useful stuff in the settings menu too, such as setting all the defaults for code style for a specified language, such as Apex or Javascript. All that will be automatically formatted for you. You can export all this to other developers on your team too, and make everyone’s code consistent. That’s an example of the convenient, time-saving efficiency of an IDE.
Another option is to run your Apex tests in the IDE, and it will display coverage next to the classes that it tests. Yes, you can do that in developer consoles too, but an IDE like IntelliJ will conveniently show you which classes the test covered, and even break down what happened in those tests, such as line coverage. Pretty cool, huh? And this is just the start; an IDE can do a whole lot more!
To recap, an IDE like IntelliJ will make your life as a programmer faster, more convenient, more direct, more consistent, and more intuitive than ever before, acting like a souped-up developer console with more options so you can get more work done. Give it a try, and see what you can accomplish with the power of an IDE! Until next time!
Get Coding With The Force Merch!!
We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
The Salesforce Definition of What the Apex Language is
Let’s go over what Apex actually is, and when you, as a developer or administrator, should use it when creating custom functionality in your Salesforce orgs.
Apex is a proprietary development language created specifically for Salesforce’s own platform. Apex looks and feels similar to Java (not Javascript) or C#. The Apex language allows you to build custom functionality that Salesforce’s point-and-click tools can’t support or do on their own. This means that with Apex, you can expand Salesforce’s functionality and build absolutely anything that you or your users can dream up for your Salesforce instance. The sky is the limit with the power of Apex! Go ahead and give it a try, and see what you can do with it.
A Simpler Explanation of What the Apex Language Is
Apex is a strongly typed object-oriented programming language, but what does that really mean? Let’s look at an example.
This example is a representation of a calculator for opportunities in our org. Like a real, physical calculator, this code calculator could potentially have the ability to add, subtract, multiply, and divide value. My opportunity calculator class above uses methods to add and subtract values, all while creating a representation of an object and the many ways in which that object can interface with its users (such as pressing a calculator’s buttons to do some math). There’s much more I could say about object-oriented programming, but that can should probably wait for a future blog post. It’s too much to unpack here, but eventually, we’ll check it out together!
There are four key things you need to know about object-oriented programming: encapsulation, abstraction, inheritance, and polymorphism. If you’d like to know more about those four in greater detail, check out my video over OOP in Apex here!
At a very high-level, object-oriented programming (OOP) is the representation of an object and its functionality in code. Now, what is a strongly typed language? First, consider variables, or a way to represent a value. When I create a variable called numberValue and I set it equal to 1, I’m declaring that variable as an integer, or a way to declare a number in Apex (among many other development languages). I’m declaring it as type Integer, but note that if I just declared that 1 as a number value without “Integer,” Apex wouldn’t accept it, nor would Apex allow me to save it like that. In short, Apex needs me to specify the type of value I’m trying to store: Integer. I must also specify what kind of value I want to return from those methods if I want to return something.
So, when I declare my method, I’m saying that when my method is done executing, it will return an integer. In programming languages that aren’t strongly typed, you don’t have to declare variables as a specific type (like Integer). Javascript is an example, where you can simply say that the variable you’re declaring equals 1 or Cool or whatever you can think up, and you don’t define a type for those variable.
In short, strongly typed OOP language means you’ve got to tell the code what it’s supposed to return and what your variable types are.
When Should You Actually Choose to Use Apex?
When exactly should you use the Apex development language? It’s a bit subjective, but also not. Often, you’ll find that out-of-the-box, point-and-click Salesforce stuff doesn’t work well with what your users actually need so they can do their job, and that’s when you use Apex. As a Salesforce user or admin, you must know all the administrative capabilities and know how to create new objects with their own fields, among other things. This is so you know when it’s proper to use administrative tools, or when you should use custom development instead.
Usually, you’ll need to use Apex development in one of two different scenarios. The first is, as mentioned earlier, when your out-of-the-box, point-and-click tools aren’t enough to build what you’re trying to make for your users. The second is when your org scales up to a huge size with lots of users (such as the 500-user mark), where your point-and-click tools can’t handle the sheer volume of daily transactions your users are making. When you reach that point, it’s time for Apex code to take over and work its magic!
Get Coding With The Force Merch!!
We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Welcome to the second episode of my Salesforce Apex Master Class! Today, I’ll show you how to set up your own Salesforce developer org!
How to Set Up a Free Dev Org!
It’s easy to set up your own Salesforce developer org, even if it’s your first time using the Salesforce platform. First, you’ll visit developer.salesforce.com/signup, then fill in your information and dive right in. It’s quick and easy, but take note that with Salesforce, you’re living in “the cloud” (aka sharing space on a server with other businesses), and there are limits imposed on your orgs because of that! Limits are imposed on things like, the amount of data you can store in your org or the number of queries you can do in your org in a single execution context.
In your developer org, those numbers tend to be pretty low compared to what you’d experience when using regular organizations. I’ve found some ways to bypass those limits, such as with “big objects”, but I probably should not suggest them as they certainly aren’t “best practice” and I’m not sure Salesforce would condone them!
One note when signing up for Salesforce: if you’ve ever created a Salesforce org or if you’ve been placed in a Salesforce org before, and you used your email address as a username in those orgs anywhere at all, you can’t reuse that email address (usernames must be unique across ALL instances of Salesforce in existence, not just your own org). Instead, you’ll make up something new, or a least revise your email address when using it as a username. Such as adding a few letters or numbers at the end.
Once all that’s done, you’ll receive an email that will inform you that your Salesforce org has been created for you! It’ll take a few minutes to get that email, though, so be patient. Next up, you’ll verify your new account via that email you just received. You’ll click “Verify my account” and set up your password. Once all that’s done, you’ll be looking at your very own Salesforce org, and you’re ready for work! It’s quick, easy, and doesn’t cost you a dime.
That’s all for now. Thanks for reading, and happy coding!
Get Coding With The Force Merch!!
We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
You may have heard of Salesforce before, and that developers on this platform get paid good money, but what exactly is Salesforce, anyway? No matter how much you earn, your work will suffer unless you actually enjoy what you’re doing. So before you dive into this career, let’s discover what Salesforce is and what you can expect to do as a developer on the platform!
Salesforce is a customer relationship management (CRM) platform, a vital tool for marketing sales, commerce, service, and IT teams to work in unison and be of service to their customers anywhere and everywhere. As of this writing, Salesforce stands as the #1 CRM platform available, overtaking competing platforms such as Siebel, Oracle, and SAP, among others. For context, CRM’s market share in 2015 was 19.7%, and as of today, it rose only slightly to 19.8%, with minor fluctuations. Meaning, CRM and Salesforce are probably going to remain steady for the foreseeable future, though there’s no guarantee of that. If you’re entering the Salesforce Ecosystem just because it’s the #1 CRM platform, don’t bank on that, even though it hasn’t for awhile, it could shift at any time. At one point (not long ago) Siebel was the #1 CRM platform, now you rarely hear of them.
That said, whether or not Salesforce stays at #1, it’s an outstanding platform that can do you a lot of good, and if you know your stuff, it could pay off handsomely. Now let’s go into more detail.
What You Will Likely Build as an SF Dev
As mentioned above, you’ll most likely use Salesforce for work in IT, marketing sales, commerce, services (such as help desk services), and a few others. IT, marketing sales, commerce, and services are probably going to be the central core of your work, with a few exceptions, so those are a good starting point for your use of Salesforce. Personally, I worked on 50 projects for 20 different clients using Salesforce, nearly all of them involving IT, marketing sales, commerce, and services.
So, what can you expect to build? You could build configuration point-and-click administration stuff and custom development in those areas described above, for example. I built extremely customized sales cloud instances and very large custom marketing applications that can sit on top of Salesforce or to be within a particular organization’s instance, just to name two examples.
Your overall goal: to take a client’s older or underperforming platform and upgrade it with Salesforce. This work can be done pretty quickly, too, and Salesforce’s brand prides itself on that fact. Once your work is done, any team working in IT, marketing sales, commerce, and services can coordinate their work and do it faster, more easily, and with better analytics with their daily work.
With that in mind, you might expect to move into Salesforce pretty quickly for two reasons: one, because of Salesforce’s reputation for speed, and two, because Salesforce offers a huge shell for making it easy for devs to get their work done faster than ever. Along the way, you’ll also want to understand Salesforce’s administrative side, through which you will build database tables, and set up anything else you’d have to develop on your own. When you use Salesforce, a lot of the work is already done for you.
In short, it’s incredibly important for you to get a handle on all this admin work with Salesforce. Some might disagree, which is fine, but having worked as a Java and PHP developer myself, Salesforce’s admin features can cut out a lot of clutter for developer work so I can focus on what matters most: writing code. I greatly enjoy Salesforce’s streamlined feel for my development work, and it was an easy and enjoyable transition to this platform while cutting out time-consuming remedial work. Perhaps the same will be true for you, too!
De-Mystifying Some SF Dev Misconceptions
You might have heard some misconceptions online about Salesforce, such as people saying that you don’t have to write much code with Salesforce, or that outdated languages are being used with it, or that there are few customization options with this platform, among other issues. Those were somewhat true in the past (and still a bit true today), but Salesforce is stronger and more effective than these rumors would suggest. Let’s review.
Salesforce didn’t have much IDE support early on (I have a separate video on the topic), but fortunately, IDE support is everywhere today. Meanwhile, maybe you’ve heard that you can’t do source-driven development in Salesforce, which would be a serious issue. Good news: you absolutely can use source-driven development with Salesforce, such as with scratch orgs, if a developer wants to.
As for outdated programming languages: yes, you’ll use the slightly dated language Apex, which can be compared to what Java was like 6-7 years ago. But don’t let that discourage you! No matter its age, Apex provides nearly everything you need for work in Salesforce, just lacking a few of the most advanced capabilities of coding languages. If that’s ever a concern for you, try using open source repos to fill in the gaps.
Another rumor says that with Salesforce, you can’t work with modern front-end technologies. Up until two years ago, that was true, but with today’s lightning web components, you can pretty much perform whatever modern UI front-end development you need.
The only caveat to working with Lightning Web Component’s within Salesforce is lightning locker service, among a few other issues. Locker Service, which is due for an update soon which might render this sentence incorrect, makes it challenging to use outside JavaScript Libraries. Many JS Libraries that you could easily import into a Node JS project (or equivalent) would require you to re-write some of its code (or a lot of its code) just to get it to function inside of an LWC due to Locker Service restrictions.
Typescript also won’t work out very well in Salesforce, for example, being hampered by a variety of problems. While it can be done there is just so much out-of-the-box Salesforce stuff that it won’t cooperate with that it renders it fairly useless.
As a developer, you’ll have endless options with Salesforce, and I myself have made hundreds of custom applications with Salesforce. You’ll simply have to keep those limitations in mind and plan accordingly. Once in a while, for example, you might build an application elsewhere, such as with AWS, then pipe it into Salesforce. Anything you can’t make in Salesforce, you can just slot right in.
On a final note, some folks might think that anyone who’s using Salesforce is mostly an admin, just doing point-and-click stuff instead of coding. This is simply not true, as a developer on the platform you’ll be expected to do development every single day. I’ve been a developer on the Salesforce platform for the past seven years, I’ve done development work every single day. Coding comes first and foremost with Salesforce as a developer on the platform, I can assure you, and it’s simply a pleasure for any developer like me to use.
Salesforce, in short, isn’t for everyone, but for the right developers, it’s a dream come true. Give it a try, and see what you can create! Until next time!
Get Coding With The Force Merch!!
We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
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.
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:
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:
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:
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.
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.
//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))
}
}
);
//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))
}
}
);
//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.
What is the Separation of Concerns Design Principle?
Basically separation of concerns is the practice of putting logical boundaries on your code. Putting these logical boundaries on your code helps make your code easier to understand, easier to maintain and much more flexible when it needs to be altered (and every code base ever has to be altered all the time).
In the Salesforce Ecosystem there are three major areas of concern we ideally should separate our code into. They are the following:
The Service Layer:
The Service Layer should house 100% of your non-object specific business logic (object specific logic is most often handled by the domain layer). This is, the logic that is specific to your organizations specific business rules. Say for instance you have a part of your Salesforce App that focuses on Opportunity Sales Projections and the Opportunity Sales Projection App looks at the Oppotunity, Quote, Product and Account objects. You might make an OpportunitySalesProjection_Service apex class that houses methods that have business logic that is specific to your Opportunity Sales Projection App. More information on the Service Layer here.
The Domain Layer:
The Domain Layer houses your individual objects (database tables) trigger logic. It also houses object specific validation logic, logic that should always be applied on the insert of every record for an object and object specific business logic (like how a task my be created for a specific object type, etc). If you used the Account object in your org you should create a Domain class equivalent for the Account object through the use of a trigger handler class of some sort. More information on the Domain Layer here.
The Selector Layer:
The Selector Layer is responsible for querying your objects (database tables) in Salesforce. Selector layer classes should be made for each individual object (or grouping of objects) that you intend to write queries for in your code. The goal of the selector layer is to maintain query consistency (consistency in ordering, common fields queried for, etc) and to be able to reuse common queries easily and not re-write them over and over again everywhere.
Why is it Useful?
There are many benefits to implementing SoC, most of which were outlined above, but here are the highlights:
1) Modularizes your code into easy to understand packages of code making it easier to know what code controls what, why and when.
2) Massively reduces the amount of code in your org by centralizing your logic into different containers. For instance, maybe you currently have 13 different apex controllers that house similar case business logic. If you placed that business logic into a service class and had all 13 apex controllers call that service class instead your life would be a whole lot simpler. This can get a lot more abstract and turn into absolutely unprecedented code reduction, but we have to start somewhere a bit simpler.
3) Separation of Concerns lends itself to writing extremely well done and comprehensive Unit Tests. It allows for easy dependency injection which allows you to, in test classes, mock a classes dependent classes. We’ll go over this more when we get to the Unit testing and Apex Mocks section of this tutuorial, but if you want a quick and easy explanation, please feel free to check out my video covering dependency injection and mocking in apex.
How does the Apex Common Library help with SoC?
The Apex Common Library was quite literally built upon the three layers outlined above. It provides an unrivaled foundation to implement SoC in your Salesforce org. When I started this tutorial series I was not convinced it was the absolute best choice out there, but after hundreds of hours of practice, documentation, experimentation with other similar groupings of libraries, etc I feel I can confidently say (as of today) that this is something the community is lucky even exists and needs to be leveraged much more than it is today.
Example Code
All of the code examples in this repo are examples of SoC in action. You can check the whole repo out here. For layer specific examples check out the layer specific pages of this wiki.
The Apex Common Library is an open source library originally created by Andy Fawcett when he was the CTO of FinancialForce and currently upkept by many community members, but most notably John Daniel. Aside from its origins and the fflib_ in the class names, it is no longer linked to FinancialForce in any way.
The library was originally created because implementing the Separation of Concerns Design Principle is difficult no matter what tech stack you’re working in. For Salesforce, the Apex Common Library was built to simplify the process of implementing Separation of Concerns as well as assist in managing DML transactions, creating high quality unit tests (you need the Apex Mocks library to assist with this) and enforcing coding and security best practices. If you want an exceptionally clean, understandable and flexible code base, the Apex Common library will greatly assist you in those endeavors.
Does The Apex Common Library Implement Separation of Concerns for me Automatically?
Unfortunately it’s not that simple. This library doesn’t just automatically do this for you, no library could, but what it does is give you the tools to easily implement this design principle in your respective Salesforce Org or Managed Package. Though there are many more classes in the Apex Common Library, there are four major classes to familiarize yourself with to be able to implement this, four object oriented programming concepts and three major design patterns. Additionally it’s beneficial if you understand the difference between a Unit Test and an Integration Test. We’ll go over all of these things below.
The Four Major Classes
1) fflib_Application.cls – This Application class acts as a way to easily implement the Factory pattern for building the different layers when running your respective applications within your org (or managed package). When I say “Application” for an org based implementation this could mean a lot of things, but think of it as a grouping of code that represents a specific section of your org. Maybe you have a service desk in your org, that service desk could be represented as an “Application”. This class and the factory pattern are also what makes the Apex Mocks Library work, without implementing it, Apex Mocks will not work.
2) fflib_SObjectDomain.cls – This houses the base class that all Domain classes you create will extend. The many methods within this class serve to make your life considerably easier when building your domain classes, for each object that requires a trigger, out. You can check out my Apex Common Domain Layer Implementation Guide for more details.
3) fflib_SObjectSelector.cls – This houses the base class that all Selector classes you create will extend. The many methods within this class will serve to make your life a ton easier when implementing a selector classes for your various objects in your org. You can check out my Apex Common Selector Layer Implementation Guide
1) Inheritance) – When a class inherits (or extends) another class and the sub class gets access to all of its publicly accessible methods and variables.
2) Polymorphism) – When a class uses overloaded methods or overrides an inherited classes methods.
3) Encapsulation) – Only publishing (or making public) methods and class variables that are needed for other classes to use it.
4) Interfaces) – An interface is a contract between it and a class that implements it to make sure the class has specific method signatures implemented.
Quality question… I mean honestly wtf is this thing? Lol, sorry, let’s figure it out together. The fflib_Application class is around for two primary purposes. The first is to allow you an extremely abstract way of creating new instances of your unit of work, service layer, domain layer and selector layer in the Apex Common Library through the use of the factory pattern. The second is that implementing this application class is imperative if you want to leverage the Apex Mocks unit testing library. It depends on this Application Factory being implemented.
Most importantly though, if you understand how interfaces, inheritance and polymorphism work implementing this class allows you to write extremely abstract Salesforce implementations, which we’ll discuss more in sections below
Why is this class used?
Ok, if we ignore the fact that this is required for us to use the Apex Mocks library, understanding the power behind this class requires us to take a step back and formulate a real world Salesforce use case for implementing it… hopefully the following one will be easy for everyone to understand.
Say for instance I have a decent sized Salesforce instance and our business has a use case to create tasks across multiple objects and the logic for creating those tasks are unique to every single object. Maybe on the Account object we create three new tasks every single time we create an account and on the Contact object we create two tasks every single time a record is created or updated in a particular way and we ideally want to call this logic on the fly from anywhere in our system.
No matter what we should probably place the task creation logic in our domain layer because it’s relevant to each individual object, but pretend for a second that we have like 20 different objects we need this kind of functionality on. Maybe we need the executed logic in an abstract “task creator” button that can be placed on any lightning app builder page and maybe some overnight batch jobs need to execute the logic too.
Well… what do we do? Let’s just take the abstract “Task Creator” button we might want to place on any object in our system. We could call each individual domain layer class’s task creation logic in the code based on the object we were on (code example below), but that logic tree could get massive and it’s not super ideal.
Task Service example with object logic tree
public with sharing class Task_Service_Impl
{
//This method calls the task creators for each object type
public void createTasks(Set recordIds, Schema.SObjectType objectType)
{
if(objectType == Account.getSObjectType()){
new Accounts().createTasks(recordIds);
}
else if(objectType == Case.getSObjectType()){
new Cases().createTasks(recordIds);
}
else if(objectType == Opportunity.getSObjectType()){
new Opportunities().createTasks(recordIds);
}
else if(objectType == Taco__c.getSObjectType()){
new Tacos().createTasks(recordIds);
}
else if(objectType == Chocolate__c.getSObjectType()){
new Chocolates().createTasks(recordIds);
}
//etc etc for each object could go on for decades
}
}
Maybe… just maybe there’s an easier way. This is where the factory pattern and the fflib_Application class come in handy. Through the use of the factory pattern we can create an abstract Task Service that can (based on a set of records we pass to it) select the right business logic to execute in each domain layer dynamically.
//Creation of the Application factory class
public with sharing class Application
{
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.DomainFactory domain =
new fflib_Application.DomainFactory(
Application.selector,
new Map<SObjectType, Type>{Case.SObjectType => Cases.Constructor.class,
Opportunity.SObjectType => Opportunities.Constructor.class,
Account.SObjectType => Accounts.Constructor.class,
Taco__c.SObjectType => Tacos.Constructor.class,
Chocolate__c.SObjectType => Chocolates.Constructor.class}
);
}
//The task service that anywhere can call and it will operate as expected with super minimal logic
public with sharing class Task_Service_Impl implements Task_Service_Interface
{
//This method calls the task creators for each object type
public void createTasks(Set<Id> recordIds, Schema.SObjectType objectType)
{
fflib_ISObjectDomain objectDomain = Application.domain.newInstance(recordIds);
if(objectDomain instanceof Task_Creator_Interface){
Task_Creator_Interface taskCreator = (Task_Creator_Interface)objectDomain;
taskCreator.createTasks(recordIds);
}
}
}
You might be lookin at the two code examples right now like wuttttttttt how thooooo?? And I just wanna say, I fully understand that. The first time I saw this implemented I thought the same thing, but it’s a pretty magical thing. Thanks to the newInstance() methods on the fflib_Application class and the Task_Creator_Interface we’ve implemented on the domain classes, you can dynamically generate the correct domain when the code runs and call the create tasks method. Pretty wyld right? Also if you’re thinkin, “Yea that’s kinda nifty Matt, but you had to create this Application class and that’s a bunch of extra code.” you need to step back even farther. This Application factory can be leveraged ANYWHERE IN YOUR ENTIRE CODEBASE! Not just locally in your service class. If you need to implement something similar to automatically generate opportunities or Accounts or something from tons of different objects you can leverage this exact same Application class there. In the long run, this ends up being wayyyyyyyyy less code.
If you want a ton more in depth explanation on this, please watch the tutorial video. We code a live example together so I can explain this concept. It’s certainly not easy to grasp at first glance.
fflib_Application inner classes and methods cheat sheet
Inside the fflib_Application class there are four classes that represent factories for the your unit of work, service layer, domain layer and selector layer.
//The constructor for this class requires you to pass a list of SObject types in the dependency order. So in this instance Accounts would always be inserted before your Contacts and Contacts before Cases, etc.
public static final fflib_Application.UnitOfWorkFactory UOW =
new fflib_Application.UnitOfWorkFactory(
new List<SObjectType>{
Account.SObjectType,
Contact.SObjectType,
Case.SObjectType,
Task.SObjectType}
);
After creating this unit of work variable above ^ in your Application class example here there are four important new instance methods you can leverage to generate a new unit of work:
1) newInstance() – This creates a new instance of the unit of work using the SObjectType list passed in the constructor.
newInstance() Example Method Call
public with sharing class Application
{
public static final fflib_Application.UnitOfWorkFactory UOW =
new fflib_Application.UnitOfWorkFactory(
new List<SObjectType>{
Account.SObjectType,
Contact.SObjectType,
Case.SObjectType,
Task.SObjectType}
);
}
public with sharing class SomeClass{
public void someClassMethod(){
fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance();
}
}
newInstance(fflib_SObjectUnitOfWork.IDML dml) Example Method Call
public with sharing class Application
{
public static final fflib_Application.UnitOfWorkFactory UOW =
new fflib_Application.UnitOfWorkFactory(
new List<SObjectType>{
Account.SObjectType,
Contact.SObjectType,
Case.SObjectType,
Task.SObjectType}
);
}
//Custom IDML implementation
public with sharing class IDML_Example implements fflib_SObjectUnitOfWork.IDML
{
void dmlInsert(List<SObject> objList){
//custom insert logic here
}
void dmlUpdate(List<SObject> objList){
//custom update logic here
}
void dmlDelete(List<SObject> objList){
//custom delete logic here
}
void eventPublish(List<SObject> objList){
//custom event publishing logic here
}
void emptyRecycleBin(List<SObject> objList){
//custom empty recycle bin logic here
}
}
public with sharing class SomeClass{
public void someClassMethod(){
fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance(new IDML_Example());
}
}
3) newInstance(List <SObjectType> objectTypes) – This creates a new instance of the unit of work and overwrites the SObject type list passed in the constructor so you can have a custom order if you need it.
newInstance(List <SObjectType> objectTypes) Example Method Call
public with sharing class Application
{
public static final fflib_Application.UnitOfWorkFactory UOW =
new fflib_Application.UnitOfWorkFactory(
new List<SObjectType>{
Account.SObjectType,
Contact.SObjectType,
Case.SObjectType,
Task.SObjectType}
);
}
public with sharing class SomeClass{
public void someClassMethod(){
fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance(new List<SObjectType>{
Case.SObjectType,
Account.SObjectType,
Task.SObjectType,
Contact.SObjectType,
});
}
}
newInstance(List objectTypes, fflib_SObjectUnitOfWork.IDML dml) Example Method Call
public with sharing class Application
{
public static final fflib_Application.UnitOfWorkFactory UOW =
new fflib_Application.UnitOfWorkFactory(
new List<SObjectType>{
Account.SObjectType,
Contact.SObjectType,
Case.SObjectType,
Task.SObjectType}
);
}
//Custom IDML implementation
public with sharing class IDML_Example implements fflib_SObjectUnitOfWork.IDML
{
void dmlInsert(List<SObject> objList){
//custom insert logic here
}
void dmlUpdate(List<SObject> objList){
//custom update logic here
}
void dmlDelete(List<SObject> objList){
//custom delete logic here
}
void eventPublish(List<SObject> objList){
//custom event publishing logic here
}
void emptyRecycleBin(List<SObject> objList){
//custom empty recycle bin logic here
}
}
public with sharing class SomeClass{
public void someClassMethod(){
fflib_ISObjectUnitOfWork unitOfWork = Application.UOW.newInstance(new List<SObjectType>{
Case.SObjectType,
Account.SObjectType,
Task.SObjectType,
Contact.SObjectType,
}, new IDML_Example());
}
}
//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 fflib_Application.ServiceFactory(new Map<Type, Type>{
SObject_SharingService_Interface.class => SObject_SharingService_Impl.class
});
After creating this service variable above ^ in your Application class example here there is one important new instance method you can leverage to generate a new service class instance:
1) newInstance(Type serviceInterfaceType) – This method sends back an instance of your service implementation class based on the interface you send in to it.
newInstance(Type serviceInterfaceType) Example method call:
//This is using the service variable above that we would've created in our Application class
Application.service.newInstance(Task_Service_Interface.class);
//This allows us to create a factory for instantiating selector classes. You send it an object type and it sends
//you the corresponding selectory layer class.
//Example initialization: fflib_ISObjectSelector objectSelector = Application.selector.newInstance(objectType);
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}
);
After creating this selector variable above ^ in your Application class example here there are three important methods you can leverage to generate a new selector class instance:
1) newInstance(SObjectType sObjectType) – This method will generate a new instance of the selector based on the object type passed to it. So for instance if you have an Opportunity_Selector class and pass Opportunity.SObjectType to the newInstance method you will get back your Opportunity_Selector class (pending you have configured it this way in your Application class map passed to the class.
newInstance(SObjectType sObjectType) Example method call:
//This is using the selector variable above that we would've created in our Application class
Application.selector.newInstance(Case.SObjectType);
2) selectById(Set<Id> recordIds) – This method, based on the ids you pass will automatically call your registered selector layer class for the set of ids object type. It will then call the selectSObjectById method that all Selector classes must implement and return a list of sObjects to you.
selectById(Set<Id> recordIds) Example method call:
//This is using the selector variable above that we would've created in our Application class
Application.selector.selectById(accountIdSet);
3) selectByRelationship(List<sObject> relatedRecords, SObjectField relationshipField) – This method, based on the relatedRecords and the relationship field passed to it will generate a selector layer class for the object type in the relationship field. So say you were querying the Contact object and you wanted an Account Selector class, you could call this method it, pass the list of contacts you queried for and the AccountId field to have an Account Selector returned to you (pending that selector was configured in the Application show above in this wiki article).
selectByRelationship(List<sObject> relatedRecords, SObjectField relationshipField) Example method call:
//This is using the selector variable above that we would've created in our Application class
Application.selector.selectByRelationship(contactList, Contact.AccountId);
//This allows you to create a factory for instantiating domain classes. You can send it a set of record ids and
//you'll get the corresponding domain layer.
//Example initialization: fflib_ISObjectDomain objectDomain = Application.domain.newInstance(recordIds);
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}
);
After creating this domain variable above ^ in your Application class example here there are three important methods you can leverage to generate a new domain class instance:
1) newInstance(Set <Id> recordIds) – This method creates a new instance of your domain class based off the object type in the set of ids you pass it.
newInstance(Set<Id> recordIds) Example method call:
Application.domain.newInstance(accountIdSet);
2) newInstance(List<sObject> records) – This method creates a new instance of your domain class based off the object type in the list of records you pass it.
newInstance(List<sObject> records) Example method call:
In every factory class inside the fflib_Application class there is a setMock method. These methods are used to pass in mock/fake versions of your classes for unit testing purposes. Make sure to leverage this method if you are planning to do unit testing. Leveraging this method eliminates the need to use dependency injection in your classes to allow for mocking. There are examples of how to leverage this method in the Implementing Mock Unit Testing with Apex Mocks section of this wiki.