Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Error Handling and Testing in NestJS

In this CodeLab, you'll enhance a NestJS application by implementing global error handling strategies and creating a custom exception filter to improve and standardize error responses. Additionally, you'll develop both unit and end-to-end tests covering various aspects of the application to ensure overall reliability for this application.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 45m
Published
Clock icon Mar 13, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Introduction

    Error handling involves anticipating, capturing, and managing unexpected conditions in an application to ensure it remains stable, provides meaningful feedback, and facilitates debugging. Testing is the practice of systematically verifying that software behaves as expected through techniques like unit, integration, and end-to-end testing.

    Both of these concepts can go hand in hand to help catch bugs early and ensure long-term reliability.


    Error Handling and Testing in NestJS

    NestJS addresses error handling through its built-in and custom exception filters, ensuring consistent HTTP responses and logging of errors. This modular approach lets developers tailor error handling for different scopes across the application.

    For testing, NestJS leverages Jest as its default testing framework. Its dependency injection and modular architecture facilitate the isolation of components, allowing developers to simulate real-world scenarios and verify application behavior.


    Working with the Application

    In this lab, you will incorporate both custom and built-in exceptions for this NestJS application. Afterwards, you will look into writing unit and end-to-end tests using tools provided by the NestJS framework. As you progress through the lab, you can interact with it when running the application through the Swagger interface, which can be found in the Simple Web Browser tab after you have run the application.

    You can run the application in the Run Server terminal with either npm run start or npm run start:dev. The start:dev version will set it in watch mode, which will dynamically refresh whenever you make any changes to files. After running the application, make sure to add api to the url in the simple browser to access the Swagger interface.

    There is also a solution directory for you to check your implementations at any time.

  2. Challenge

    Built-in Exceptions

    NestJS comes with a global exception filter that is meant to catch errors and exceptions that occur. The framework comes with many built-in exceptions that correspond to the standard HTTP error responses.


    Review the item.service.ts

    Open the src/item/item.service.ts file. Inside this file, you will find a completed service for the Item resource. For this step, you will need to modify the findOne() and remove() methods to throw a specific exception to handle certain inputs.


    Throwing a built-in Exception

    Throwing a built-in HTTP exception in NestJS is as simple as the following:

    throw new HTTPExceptionType('insert error message')
    

    Alternatively, you can also utilize the optional options object parameter in an exception to provide more detail for a caught exception such as:

    throw new HTTPExceptionType('insert error message', {
      cause: new Error(),
      description: 'insert more details',
    })
    

    Inside the findOne() method, you will need to throw two specific errors. Similarly to findOne(), you will need to add a conditional to throw a built-in NotFoundException within remove(). ## Conclusion

    You have successfully implemented and utilized the global exception filter that NestJS provides through its built-in exceptions. Next, you will look into custom exception filters for more specialized uses.

  3. Challenge

    Custom Exception Filters

    While the built-in exceptions provided by NestJS can handle most error handling needs, there may be times when you need full granular control or a more specific exception filter. Enhanced exception logging beyond simple error messages is one such example.


    Review LoggingExceptionFilter

    The custom exception filter you will be implementing is the LoggingExceptionFilter class located in src/filters/LoggingExceptionFilter.filter.ts. Most of the business logic for the filter has already been done, but you will need to add some finishing touches and register it under Nest's dependency injection system.

    Custom Exception Filters can be designed to apply to different scopes of an application, whether it's specific to a single method, specific to a certain controller, or even bound globally across the entire application.


    The @Catch() decorator provided by NestJS allows you to mark a class to pick up certain exceptions. This can hold more than just one exception type to catch as long as they are comma-separated. For this filter, you will make it a catch-all filter. To obtain control over the request-response flow for your exception filter, you will need to hook into these objects using an execution context such as ArgumentsHost for the underlying platform. By default, most NestJS applications(including this one) utilize Express, so you will be hooking into the Request and Response objects from Express. Now that you've hooked into the underlying Request object, the catch() method can now utilize them to retrieve information on caught exceptions and formulate a more in-depth report for them. Now you just need to return this information through the Response object. Now that you've completed the custom exception filter, you will need to register it for the NestJS framework to recognize it. As mentioned previously, this filter is meant to be a catch-all filter that is applied globally rather than to a specific controller or method. Head to the app.module.ts file to bind it. ## Conclusion

    With this, you've successfully setup a custom catch-all exception filter that provides a more informative overview for all HTTP and unrecognized exceptions. Next, you will dive into some unit and end-to-end testing in NestJS.

  4. Challenge

    Testing

    Testing in NestJS is done by default through Jest, so those who are familiar with Jest already understand almost everything there is to it. In NestJS, tests are typically either unit tests or end-to-end(e2e) tests, which are conducted through the usage of the supertest library to simulate requests.

    One other thing that NestJS provides specifically for testing is the Test and TestingModule classes, which can be utilized in your test files to mock your NestJS application while supporting dependency injection.


    Unit and End-to-End Test Files

    Per NestJS convention you will usually find your unit test files co-located with the files they are related to, whereas e2e tests will usually be found in the test directory. For this lab, you will be working on the item.service.spec.ts unit test in the src/item directory to test findOne(). The delete-remove.e2e-spec.ts e2e test within test will be used to test remove().

    First, take a look at item.service.spec.ts.


    The BeforeAll() fixture runs before all test cases and instantiates a TestingModule. You can inject the ItemService as a dependency into this TestingModule which will make it available for testing. This is already done for you through boilerplate generation, but you will need to assign the ItemService to a variable. The first test case marked by the first it() function will test whether your findOne() method properly returns a BadRequestException when provided an invalid input. The next test case needs to test that your findOne() method throws a NotFoundException when given a certain input and that the error response matches the expected error response. The last test case in your unit test needs to test that the findOne() method returns the correct Item.

  5. Challenge

    Testing(Cont.)

    Now you will need to move on to the e2e test for remove(). Take a look at delete-remove.e2e-spec.ts. This e2e test looks just like your unit test, but this time it includes an INestApplication called app. This variable will be used to mock your full application when testing your endpoint attached to remove().

    Before you can start working on your test case, you will need to instantiate this app using the TestingModule. When performing e2e testing, it's also best practice to close your app instance after all test cases have been run. Lastly, you will complete the test case that involves using the remove() method tied to the DELETE endpoint. A good portion of the test case has already been provided to you, all that's left for you to add is to make simulated request calls from the supertest library. ## Conclusion

    If you've made it here then you have successfully implemented built-in exceptions along with a custom exception filter for your NestJS application. Furthermore, you've also managed to witness and work with Nest's Test and TestingModule classes to facilitate testing for the application.

    Great job on completing this lab!

George is a Pluralsight Author working on content for Hands-On Experiences. He is experienced in the Python, JavaScript, Java, and most recently Rust domains.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.