Introduction: Why Use a Mock Database?

Welcome back! In the last lesson, you learned how to organize your code by moving business logic into a service layer. Now, you are ready to connect your service to a data source. In real-world applications, this data source is usually a database. However, when learning or testing, it’s common to use a mock database instead.

Common database options include SQL (like PostgreSQL or MySQL), NoSQL (like MongoDB), or cloud-hosted databases. These real databases persist your data between sessions and support complex queries. For now, we’re using a mock database to simulate this behavior using plain arrays in memory. It’s faster to set up and ideal for learning or prototyping — but keep in mind that all data is reset when the server restarts.

A mock database is a simple, fake version of a real database. It lets you store and retrieve data in memory, using arrays or objects, without needing to set up a real database server. This makes it much easier and faster to develop and test your API.

In this lesson, you will see how to connect your NestJS service layer to a mock database so your API can return real data instead of hardcoded values.

Quick Recap: Where We Are Now

Let’s quickly remind ourselves of the current project structure. You already have:

  • A controller that handles HTTP requests for users.
  • A service that contains the business logic for users.
  • A module that brings everything together.

Here’s a summary of the setup so far:

This controller receives requests and calls the service methods. In the last lesson, you learned how to move logic into the service. Now, let’s see how the service can get its data from a mock database.

How the Mock Database Works

Instead of connecting to a real database, we use a mock database defined in a file called mock-db.ts. This file contains a simple array of user objects:

To access this data, we use a service called DatabaseService. The DatabaseService acts as a single source of truth for data access — a pattern often used in real applications, where services abstract direct access to databases. Here’s how it looks:

Explanation:

  • The DatabaseService is marked with @Injectable(), which means it can be injected into other classes.
  • It has two methods:
    • getUsers() returns the full list of users.
    • findUserById(id) returns a single user matching the given ID, or undefined if not found.

This setup lets you simulate a real database using just a simple array.

Connecting the Service Layer to the Mock Database

Before your services can access DatabaseService, you need to make sure it’s globally registered in your application. Since multiple modules (like users, books, etc.) might use it later, it’s a good idea to mark it as a global provider in AppModule.

Explanation:

  • @Global() makes DatabaseService accessible in all other modules without needing to import it repeatedly.
  • exports: [DatabaseService] ensures that other modules like UsersModule can inject and use it.

🔐 In large projects, you might move database logic to a DatabaseModule and import it into feature modules. But for now, this setup is a clean and efficient way to share your mock DB.

Connecting the Service Layer to the Mock Database

Now, let’s see how the UsersService uses the DatabaseService to fetch data. Here’s the relevant code:

Explanation:

  • The UsersService receives an instance of DatabaseService through its constructor. This is called dependency injection.
  • The findAll() method calls db.getUsers() to get all users.
  • The findOne(id) method calls db.findUserById(id) to get a specific user. If the user is not found, it throws a NotFoundException.

Example Output:
If you call findAll(), you get:

If you call findOne(2), you get:

How Controllers Access Data Through the Service

The controller acts as the entry point for HTTP requests. It calls the service methods, which in turn use the mock database. Here’s how the flow works:

Explanation:

  • When a GET request is made to /users/all, the controller calls findAll() on the service, which returns all users from the mock database.
  • When a GET request is made to /users/2, the controller calls findOne(2) on the service, which returns the user with ID 2 or a 404 error if not found.

Example Output:
Request: GET /users/all
Response:

Request: GET /users/1
Response:

Summary And What’s Next

In this lesson, you learned how to connect your NestJS service layer to a mock database using a dedicated DatabaseService. You saw how the service fetches data from the mock database and how the controller exposes this data through API endpoints.

This setup is a great way to practice building APIs before working with a real database. In the next exercises, you’ll get hands-on experience using these patterns to fetch and return data from your mock database. Keep up the good work!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal