Introduction to Unit Testing with Mocks

Welcome back to the Securing and Testing Your MVC NestJS App course! Previously, we covered session management and user authentication. Now, let's ensure our code is robust and error-free through unit testing with mocks.

What You’ll Learn

By the end of this lesson, you'll be able to:

  • Understand the significance of unit testing.
  • Set up unit testing in a NestJS project.
  • Write unit tests for controllers and services.
  • Implement mocks to test services dependent on external resources, such as databases.
What Are Unit Tests?

Unit tests validate individual components, or units, of your application in isolation. These tests focus on small functions, classes, or methods to ensure they work correctly on their own.

Key Characteristics of Unit Tests:

  • Isolated: Unit tests do not rely on external systems like databases or APIs. When a service or method interacts with such systems, you use mocks to simulate those interactions.
  • Repeatable: Unit tests should produce consistent results every time they run.
  • Fast: Since they only test individual parts of the application, they run quickly.
Setting Up Unit Tests in NestJS

Boilerplate Setup

To begin, you need to import essential modules from NestJS's testing utilities, along with the AppController and AppService. This setup is crucial to prepare the testing environment and ensure that necessary components are available for testing:

Setting Up the Test Module

Here, we set up the testing environment by using Test.createTestingModule to create a module. This module includes the AppController and AppService as providers, which ensures that each test runs in a controlled, isolated environment, minimizing external dependencies:

Writing a Test Case

In this step, we define a test case within the describe block. This test verifies the behavior of the getHello() method, ensuring it returns 'Hello World!'. This case demonstrates the syntax and structure of basic NestJS tests:

Running the Test

You can run this test by executing the following command in your terminal:

This command runs the unit tests that have been defined in your project, confirming that your controller works as expected if everything is set up correctly.

Understanding Mocks

Mocks are simulated versions of real objects, like databases or external services, used to control behavior during tests. They allow developers to isolate the test code from external dependencies, ensuring tests remain predictable and fast.

User Entity and Service Setup

Creating the User Entity

The User entity defines the structure of user objects saved in a database. This entity is equipped with fields like id, username, and password, and is decorated to map to a database table:

UserService Implementation

This service contains methods for performing CRUD operations on the User entity, interacting with the database via the repository pattern. It's a typical pattern in NestJS applications:

Writing Unit Tests for UserService with Mocks

Unit Test Setup

We mock the User repository using the getRepositoryToken() function. This enables the testing of UserService independently of a real database, illustrating the essential setup for effective unit testing in NestJS:

Writing Test Cases for the UserService

Defining Service Instance

This simple test case checks that the UserService instance is correctly defined and ready for use. It's a critical initial step in confirming setup correctness:

Testing findAll Method

This function checks the behavior of the findAll method, verifying it returns an array of users as expected. The test uses mocked data to simulate database operations:

Testing findOne Method

Here, the test verifies that the findOne method retrieves a specific user by their ID. It confirms the method functions correctly even with mocked database interactions:

Testing create Method

This test ensures the create method properly adds a new user and ensures it gets saved in the repository. It checks that both creating and saving functions are called with the right parameters:

Why Unit Testing Is Important

Unit testing is an essential part of building reliable and maintainable applications. By writing unit tests, you ensure that individual parts of your application behave correctly in isolation.

  • Early Bug Detection: Unit tests help catch errors early in development, reducing the effort and cost of fixing them later.
  • Refactoring Confidence: Unit tests provide confidence to refactor or improve code, knowing any issues introduced will be detected.
  • Documentation: Unit tests act as documentation, illustrating how a function, service, or controller is expected to behave.
  • Code Quality: Writing tests encourages better code design and structure, making your application more maintainable and scalable.

Mocks enable you to test these units in isolation without relying on real services like databases or external APIs. They allow for fast, repeatable testing during the development process, providing assurance that your application’s components work as intended.

Now it's time to write your own tests! Let's move to the practice section and start applying what you've learned!

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