This is the 10th article documenting what I’ve learned from a series of 13 Trailhead Live video sessions on Modern App Development on Salesforce and Heroku. In these articles, we’re focusing on how to combine Salesforce with Heroku to build an “eCars” app—a sales and service application for a fictitious electric car company (“Pulsar”) that allows users to customize and buy cars, service techs to view live diagnostic info from the car, and more. In case you missed my previous article, you can find the link here.
Just as a quick reminder: I’ve been following this Trailhead Live video series to brush up and stay current on the latest app development trends on these platforms that are key for my career and business. I’ll be sharing each step for building the app, what I’ve learned, and my thoughts from each session. These series reviews are both for my own edification as well as for others who might benefit from this content.
The Trailhead Live sessions and schedule can be found here:
The Trailhead Live sessions I’m writing about can also be found at the links below:
A Primer on Unit Testing
What is “unit testing” exactly and what’s different about unit testing versus another testing methodology like regression testing or smoke testing?
The “testing” part simply refers to ensuring the method in code, functionality or automation is working as expected.
Unit tests in a nutshell
Here are some examples of how unit tests can be valuable:
- Identify bugs easily and earlier
- Reduce costs related to fixing bugs and QA efforts
- Facilitate code design and refactoring
- Self-documents sets of test cases
However, these benefits are only fully realized after implementing unit testing thoughtfully and correctly. This process is often implemented poorly or skipped entirely.
A Framework for Unit Testing
Regardless of the programming language, we’re using, a good framework to base our unit test design is the Arrange, Act, and Assert (AAA) framework.
A good thing to remember with unit testing is that you are managing the “expectations” or “specifications” of the code with unit tests. This means the unit tests have something to say about code specs and what the expectations are for the code when it runs. In some cases, I’ve heard of development methods that involve writing the unit tests first, and then developing the actual code later since the unit tests can act as documentation for how the code should behave.
- Arrange: Test data setup and inserting the necessary objects/records for the unit test
- Act: Call your methods/functions or otherwise run the code you want to test and capture the result
- Assert: Create assertion statements in your unit test and compare the results you captured with expected results. You want the test to error out or notify you in some way if the result you captured deviates from the expected result.
Also if you’re using Visual Studio Code (VS Code) with LWC (and you should), you will also want to install the following extension packs for VS Code.
Unit Testing for the eCars App
So many buttons and interactions, so many ways errors can happen
If you look at the .html and .js file in the carConfigurator LWC, you’ll see that the HTML has some expected behavior and bindings to variables in the .js file. For our tests, we’re going to test that the LWC renders the expected components and values to the DOM as the test progresses. We’ll soon look at how Jest and the sfdc-lwc-jest wrapper library makes this magic happen.
First, we will need to create a testing scaffold for our unit tests with the following command in VS Code:
If the command runs successfully, your terminal should look something like this:
This creates a carConfigurator.test.js test scaffold file that we can use to build our tests. There should be a pre-built stub for the functions in the test file that you would expand upon as you build out your tests.
When you initialize your LWC project in VS Code and take a look at the package.json file, you’ll see that there are some lwc-dependencies and scripts that are included in the package. These scripts help make some of the lwc-jest magic happen.
Some lwc-jest dependencies called out in the package.json file
Unit Tests Code in Detail
it() function declaration. We’ll review some of the important highlights in this test script after you’ve scrolled through.
Import declarations are importing some of the required dependencies for running our tests. Note that you can’t use the createElement in LWC code, but you can for the unit test file.
Jest.mock is an interface that reminds me of the HTTPCalloutMock interface from Salesforce unit testing. Jest.mock mocks calls and responses to external services. In the context of our test, we can’t actually make an imperative call to our PdfCreateService APEX class/methods so we have to mock this call and response.
It’s important to note that this could be a point of failure in our tests because what we mock up could be different than how the actual PdfCreateService method behaves. Therefore, it’s a good idea to have a unit test on the Salesforce side that verifies that the PdfCreateService class is behaving correctly. This is actually exactly what we will do in the next session.
A DOM reset is needed after each unit test because the same jsdom instance is shared across all unit tests in the file. The code snippet below ensures that we’re working with a clean slate after each unit test so that we’re not getting erroneous test results due to leftovers in the jsdom after the previous unit test.
The flushPromises code snippet below helps us handle callbacks and making sure that each callback resolves properly with a Promise.
The unit tests themselves now make up the remainder of the test file. There is a lot of material to unpack in each specific unit test in terms of how to set- p the test and invoke what needs to be tested, so we’ll have some homework to do at the end of this article. However, each individual unit test will have a general form that follows something like the code below:
As you can see, even though the specific code in each unit test varies, all tests follow the same pattern from our original AAA Framework. With this framework, pretty much any element in our app, including rendering behavior, navigation, button clicks, and service callouts can be unit tested to ensure that the code is working correctly!
I’m going to be honest. From someone who came from a background of unit testing for Salesforce APEX code, the topics covered here were pretty foreign to me. I think the hardest part to grasp was the Jest methods used for testing UI behavior and rendering items. For example, “shadow DOM”, “root and child elements”, and other front-end heavy items were not things I typically worried about as a Salesforce administrator or developer.
In the next article, we will explore more unit testing but specifically for Salesforce and APEX code.
If you haven’t already joined the official Chatter group for this series, I certainly recommend you do so. You will get the full value of the experience, ask questions, and start discussions with the group. Oftentimes, there are valuable discussions and additional references available, such as presentation slides and links to other resources and references.
About me: I’m an 11x certified Salesforce professional who’s been running my own Salesforce consultancy for several years. If you’re curious about my backstory on accidentally turning into a developer and even competing on stage on a quiz show at one of the Salesforce conventions, you can read this article I wrote for the Salesforce blog a few years ago.
Thanks to Jason Sun for his kind permission to publish this article.