Mocking a monorepo

Juani Galán
Nov 22, 2020 · 5 min read
This is an actual picture of our development envirnoment after we created a mock server for our repo

With an increasing amount of services being created on our backend, our frontend development started to be impacted by how many repos and servers you needed to install locally to get the frontend going. And if we also take into consideration our frontend architecture rework, we knew we had to take action in order to have a fast and smooth development experience. That is where our monorepo mock server comes in.

A little bit about LumApps

If you do not know about LumApps, we are a global tech company with R&D teams in France that provides our customers a SaaS Digital Workplace solution, which creates a holistic workspace, integrated with several suites and collaboration tools. Want to know a little bit more about us? Head over to LumApps.com and take a look!

What we needed

Up until a couple of years ago, our frontend application was pretty straightforward to launch in your own development environment to start coding. You executed the frontend and the backend, and that was it! But since the company and the application have grown exponentially over the last couple of years, with new services created and new developers coming in to develop the product, booting the application locally was not that easy as it used to be.

These new services meant that you would need to configure them in your machine, which not only took time to setup, but also a lot of CPU, thus creating a really tough combination for our development environments. We needed a system that allowed us to:

  • Remove those services dependencies for local development and have a single server that served the data that the frontend needed for local development, and thus, increasing local development time 🚀
  • Create a set of data that all teams could reuse in order to develop their functionalities. This meant sharing that data across teams and allowing those teams to create their own data sets in order to remove/add configuration for each specific team configuration 🛠
  • Have a consistent set of data that can be reused for unit and integration tests ✅

How we did it

After some research, we found a nifty npm module called json-server that allowed us to create a full fake REST API with really no configuration at all. It is really an amazing tool, since it not only allow to mock data and create a server, but it provides a lot of core API functionalities out of the box, which makes this tool really the next level when it comes to mocking. With it, we could for example execute a POST to create a resource and the next time we do a GET for retrieving the list of resources, the recently created resource would be there! It also allows usto create express js middlewares that can be used to tweak requests and response, giving us full access to change whatever we want!

On top of that, we created a small node js file that allowed us to easily manage these mock files on a monorepo. Basically json-server needs an json entrypoint where the mock data lives, but since we are using a monorepo architecture, we wanted to each package to have their own mock data so they are the owners of that data and furthermore, it allows us to clearly see the endpoints that a package consumes. This node js file is a script executed before json-server and it:

  • Goes through each of the packages in our workspace and searches for files named api.json on the _mocks folder and combines all of them into a single file with all the data from each package. It also takes into consideration the other json-server configurations, such as routes or middlewares, and puts them all together in a single location
A user folder with a subfolder called _mocks and 3 files: api.json, routes.json and user.middleware.js
A user folder with a subfolder called _mocks and 3 files: api.json, routes.json and user.middleware.js
This is how our user package looks like with its own mocks defined
  • Writes into a predefined folder those combined files and executes json-server with those files as input.
  • This is all executed in a single command yarn mocks which creates the files and then launches json-server.
  • We also allowed each module to create different scenarios for their API responses, which we call overrides. Each package can create as many overrides as they want, which are a subset of the data that the API returns, with different values overriden and changed so that the API returns a different scenario. So for example, our API response for our notifications service looks like this:
An API response for our notifications service with the keys items, unread notifications with a value of 5 and more in true
An API response for our notifications service with the keys items, unread notifications with a value of 5 and more in true
Our notifications service returns a list of notifications to display, how many of them were not read by the user and if there are more notifications to fetch

But what if we wanted to easily launch a frontend where the user does not have any notifications at all? In that case we create the override no-notifications.api.json that overrides this file:

An API response for our notifications service with the unread notifications with a value of 0and more in false
An API response for our notifications service with the unread notifications with a value of 0and more in false
Override for a scenario where there are no notifications for the current user

At a folder level, our notifications package looks like this:

We do have a lot of different scenarios for our notifications center 😅

And in order to apply those overrides, we just launch yarn mocks -override no-notifications and our node js file will look for the different overrides created on each package with the name no-notifications and merge deep their values with the original values of the each API response. This also meant that if there are other packages that want to create an override for the no-notifications scenario they can also do that! They just need to create a file called no-notifications.api.json in their _mocks folder.

Finally, you can also apply several overrides at once by doing yarn mocks -override no-notifications,admin,no-posts. This will apply those overrides one after the other, overriding each key in the API responses in the provided order.

What is next

We still need to go through a couple more scenarios that we want to tackle to allow our developers to have a more fluid development experience:

  • Automatically create mocks from a remote backend service.
  • Periodically validate these mocks against a remote backend service in order to check that the API response did not change.
  • Open source this small node js script so those of you out there that are using monorepos and want to reuse this code can do it! Stay tuned for future developments on this subject!

LumApps Experts

The LumApps team shares their work processes and expertise…

LumApps Experts

The LumApps team shares their work processes and expertise on various topics, from engineering to product design.

Juani Galán

Written by

Frontend Software Engineer @Lumapps working with React. Former @mercadolibre @oracle. I love creating the best web experiences for developers and end Users!

LumApps Experts

The LumApps team shares their work processes and expertise on various topics, from engineering to product design.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store