NodeJS mock server:
JavaScript client:
If you've ever worked with APIs or backend developers these scenarios might sound familiar:
Luckily there's a solution to all your issues; mock APIs!
At a project I'm working on we created a mock for almost every API we talk to. Since we're running a Single Page Application (SPA), we consume a looot of data using APIs. In this blog post I'll explain how we set up our code to use either production/mock APIs and I'll provide you with a really clean, framework-independent example of how you can do so too.
For this example I'll use the genius free KanyeRest API providing a random meaningful quote of his.
To start I created a KanyeRestClient.ts
, which contains all endpoints that you need in your application.
Next to that lives the mock variant of this client; KanyeRestClientMock.ts
. It implements the same interface as the actual client, so all functions should exist in both clients.
In this file you see that not fetched from https://api.kanye.rest/
, but from another codesandbox source; the mock server. It's a really simple json-server NodeJS environment which serves our mock files. In this case only a single endpoint exists, our mock Kanye Rest endpoint:
When developing we simply run this NodeJS environment on our local machines and access the mock server from a localhost URL.
Now is where things get more interesting. You have two API clients, but how can you make sure the correct one is used? That's where dependency injection comes in handy. Even though dependency injection is a common pattern in almost every other programming language, in the front-end world it is still fairly uncommon.
A simple explanation of how dependency works over here: the API clients are the dependencies, and either one of them is injected in our application, which I will show you in a bit. The part we're looking at down here, is where the dependencies are being registered. By default the KanyeRestClient
function/dependency is bound by using a unique key; TYPE.KanyeRestClient
. We will use this key later on to inject the correct dependency.
On line 13 we see how the mock client is used. If the kanyeRest mock is enabled (in this example a sessionStorage value), the TYPE.KanyeRestClient
key is rebound to return the KanyeRestClientMock
function/dependency.
So, now we bound the correct function/dependency to the unique key, now we want to actually use it of course. Let's take a look down here. The most important part is line 8. We resolve (inject) the correct function by using our same unique ID we registered our dependency with. Now the KanyeRestClient
variable can either refer to the production client OR the mock client, but since both clients implemented the same interface, code-wise it doesn't matter which one is injected. All functions returning from the client are always the same.
Now you can fetch the data, and based on a sessionStorage value, either the production data or the mock data is returned. Hooray!
If you want to see a working demo, check out this CodeSandbox:
Just toggle the checkbox, refresh the page and see how the different dependencies are injected.
Now you might be able to imagine what possibilities this creates. You can now use mock data in your unit tests, you can use mock data to test certain scenario's in your front-end, you can use mock data to work ahead of the backend developers creating the actual API.. The possibilities are endless!
Happy coding!
Published Mar 30, 2021