Applying Test Driven Development (TDD) on Salesforce Development — Part 2: API Development
In part 1 of this TDD series we went through the concept of TDD and how one can apply it when developing on the Salesforce platform. We went through a simple use case using Apex and went through the core principles of TDD.
Welcome to part 2 of this series! In this article, I’ll go through how we can apply the TDD workflow to API development in Salesforce. We’ll use the TDD principles to create a REST-API that can be consumed by an external application and hopefully TDD will help us do this in a simple way where we can start defining the API right away by writing the test.
We’ll start with defining the purpose of this API. Let’s say we have the following requirement.
All purchasing orders of Company X are processed through an order fulfilment system. The customer orders are created from Salesforce but are then processed in another system. When an order has been fulfilled, the order in Salesforce should be updated with the correct status and a shipment tracking code. This should be done through a REST-Api request to Salesforce.
Note: the above scenario could be solved using the Salesforce Standard REST APIs but for this purpose we’ll build our own Rest API in Apex.
Let’s start with defining the API.
Since the order fulfilment system will be sending data including the tracking id and the status of the order, we’ll need to send a POST-request to the REST endpoint.
Orders POST Request:
Let’s start writing our Apex test class:
Let us go through the above code..
- We create an Order record (in the @testsetup) and replicate the above request body in our rest request using JSON.
- We’ll be using the RestContext object to supply the Apex endpoint method with our request body and our http method. The RestContext will then be accessible in our endpoint method and we can then access the request data from there.
- We call our endpoint method that I have just quickly defined here:
I like to define the actual apex class/method just to be able to call the apex method from the test class even though it haven’t yet been implemented. This makes the test more complete as I won’t necessarily have to add the method call later, it’s already there.
Let’s run the test and watch if fail.. Let’s look back at the TDD workflow:
It’s time to implement the code!
Different ways of processing JSON-data in Salesforce
When it comes to reading, writing and structuring json-data in Apex — we have a few choices..
If we go back to the TDD workflow above, our first priority is to make sure our test passes. When that milestone is reached we can then start refactoring and think of a more sophisticated solution. There for I will use the JSON.derserializeUntyped function that will do the job for us, maybe not in the cleanest of ways but it will help us make our test pass without investing too much time and effort.
Find problems early, fix them quickly
By focusing on implementing code in the simplest way possible to make our test pass, we can work fast and quickly get feedback from our test runs. The faster feedback we get, the faster we learn and we become more and more effective as Developers.
In the above example, I was quite confident that my test would pass. However, I forgot one fundamental thing about the Order object in Salesforce. I got the following error:
System.DmlException: Update failed. First exception on row 0 with id 80109000000bqFbAAI; first error: FAILED_ACTIVATION, An order must have at least one product.: []
By testing early and before starting to fine-tune my implementation — I got some valuable feedback that I can now consider in my implementation. As of now, I will add an order product to my testdata in the @testSetup method.
Passing the test
After adding some adjustments to the test data, the test now passed. From the iterations we have learned more about how our code behaves and what could potentially go wrong so we’ll have that in mind when we now refine the code.
The broader picture: The API-first approach
When building APIs in this way, we assume that we already know which API we’re building, the input parameters required and the responses returned for the different scenarios. Nowadays, organizations and teams tend to design and think about APIs before actually building it. It is called “API-first development”, quite similar to the term “API driven development”. An API-first approach assumes that design and development of an API comes before the implementation versus the opposite of the code-first approach.
It’s safe to say that TDD fits perfectly in that world.