Skip to content
Accueil » Apex Unit tests best practices

Apex Unit tests best practices

This is an article about the best practices to write Apex unit test code into Salesforce to get the better results. This requires to have a dev environment setup and ready. If you don’t have, follow this link!

First of all, I want to clarify the purpose of why I write this article about Apex unit tests best practices.

This article is more about understanding why we are doing unit tests into Salesforce (and into other language 😉 ) and how we should design them to make it helpful.

Why Apex unit tests in Salesforce?

“To reach the 75% required by SFDC to deploy my Apex Classes on PROD.”
I know I know guys, this is frustrating, especially if you’re in a hurry and… and…. and… 74% coverage :'(

In fact, Unit test is the only way, for the developer of a piece of code, to notify the team if any modification in the whole org makes this code not working anymore.

Let’s imagine you’ve written a beautyfull Apex function, called from an Apex Trigger, that updates all the products listed in an Opportunity to mark the sold date when the opportunity reaches the Stage “Closed / Won”.

It would be great to write an Apex Test class that:

  • Verifies that when the stage changes, the Products are correctly updated.
  • Fails if it’s not the case (and this point is very important, we’ll see it in the next paragraph)

That’s why, if you’re a technical leader / architect, you might put in place Apex Unit tests best practices.

ALWAYS use assertions in your Salesforce Apex test classes

For me, using Assertions in unit test classes should be mandatory.
Running the code is something good, but Assertions is the way we ENSURE that the code we have written gives the result that we expect.

That makes the code more robust.

Let’s take an Example. We want to use Salesforce to sell cars and we want to update custom field of the the product (the car sold) with the Date of today when it is referenced in an Opportunity that becomes closed / won.

The code would look be like that (I kept the code simple to be easily understandable, additionnal checks may be necessary):

Now, let’s see what the Test class looks like.
I added the data in the setup to make de code understandable.

In the above code, we can see that:

  • We check first that the sold date is not set (the opportunity is in the Stage Open)
  • After the update of the opportunity Stage, I check that the sold date have been set to the good value

So that if a developer add some more business logic on top of the existing, we make 100% SURE that the previously implemented logic remains working properly as initially implemented.

The Salesforce Ape test philosophy: an isolated environment

There is something that is simply AMAZING in the Salesforce Unit Test framework, it’s that when you run the test, all the Data you create / delete / update is completely independant from the data that reside in the org you are unning tests in.

What does it means? It means that you have the ability to create only the data you need, manipulate it, request it, the existing data will not affect the behavior of your test.

That’s something incredible. When you develop in Java or other language, it’s quite hard to have this type of way to work.
You have to setup it by yourself, run an H2 (or other lightweight) database of, but it’s not exactly the same database engine as in production… we don’t have this type of problems in Apex Unit Tests, and that’s a big advantage 🙂

Use Apex Test Data factories in you Salesforce

You’ll see, when you start writing Apex unit tests, you’ll see that you very often write the same creation of test datas.
So, it’s highly recommended to mutualize the creation of these test datas.

Let’s have a look on how we can get this done.

In the paragraph about assertions of this article, there is a “@testSetup makedata” method that create data. Let’s see how to transform these creations so that it will be reusable.

Create a Data factory Apex class for Account

Create a class an put the creation of the Account in the static method:

Repeat the same for creating factories for Opportunities Pricebook…

I’ll not detail the creation of all the classes, only the one for opportunity and opportunity line item, but I’m sure you got the point on how to create test data factory classes 😉 !

The only thing is: don’t insert the data in the factory. The principle is to generate an object that is ready to be inserted in the test class to be implemented for the scenario you identified.

Don’t use of the SeeAllData feature!

There is feature that we must talk about. It’s the @isTest(SeeAllData=True) annotation. This annotation makes the real data that is stored on the org visible from unit tests.

It’s a very very very bad practice to use it. In fact, you’ll be developing in a Sandbox that owns its own data.
You’re test will than be pushed to INTEGRATION, UAT, PRE-PROD sandboxes (depending on your release process) and all these sandboxes have their data that can be different from the data in the dev environment.

So, really, avoid to develop tests based on existing data, you’re nearly 100% sure these tests will start to fail because the data has changed.

Keep in mind that Salesforce OWD sharing rules applies in tests!

The sharing rules set up in your org will apply. So you may need to impersonate another user and so to run your code as if another user, with specific rights is trying to perform an action on the system.

For that, use the System.runAs method that takes a user in parameter and allows you to execute some code.
See some examples here.

Keep you Apex Unit tests as “unit” as possible

Unit tests are specifically designed to evaluate the behavior of individual units of code in isolation.

A unit refers to the smallest testable part of an application, typically a method or function. By adhering to the principle of small units, you ensure that each test focuses on a specific functionality or feature. This approach not only simplifies the testing process but also allows for easier debugging and maintenance.

It means that an Apex unit test best practice can be (as much as possible) writing one test per Apex method. So that, when a test starts to fail, finding the problem becomes easier since it covers only a specific piece of code!

If you need to test a method that is declared as private, no worries, just annotate this method with @testVisible and you’ll be able to access it directly in the Apex Test Class!

Use Apex Test.StartTest and Test.StopTest methods

Using Test.StartTest and Test.StopTest methods proves highly useful for resetting the governor limits in a test.

Imagine that you have to test code that nearly reaches the SFDC governor limits.
After that, you need to perform some additional SOQL queries to verify the results for example, but you have reached the limit. You test will failed although it works out of a test.

So, as an Apex unit test best practice, use the magic Test.StartTest and Test.StopTest to help you with the governor limits 🙂

Let’s see how to design the code of your test:

Leave a Reply

Your email address will not be published. Required fields are marked *