Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      June 1, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      June 1, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      June 1, 2025

      How To Prevent WordPress SQL Injection Attacks

      June 1, 2025

      7 MagSafe accessories that I recommend every iPhone user should have

      June 1, 2025

      I replaced my Kindle with an iPad Mini as my ebook reader – 8 reasons why I don’t regret it

      June 1, 2025

      Windows 11 version 25H2: Everything you need to know about Microsoft’s next OS release

      May 31, 2025

      Elden Ring Nightreign already has a duos Seamless Co-op mod from the creator of the beloved original, and it’ll be “expanded on in the future”

      May 31, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Student Record Android App using SQLite

      June 1, 2025
      Recent

      Student Record Android App using SQLite

      June 1, 2025

      When Array uses less memory than Uint8Array (in V8)

      June 1, 2025

      Laravel 12 Starter Kits: Definite Guide Which to Choose

      June 1, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Photobooth is photobooth software for the Raspberry Pi and PC

      June 1, 2025
      Recent

      Photobooth is photobooth software for the Raspberry Pi and PC

      June 1, 2025

      Le notizie minori del mondo GNU/Linux e dintorni della settimana nr 22/2025

      June 1, 2025

      Rilasciata PorteuX 2.1: Novità e Approfondimenti sulla Distribuzione GNU/Linux Portatile Basata su Slackware

      June 1, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Write Tests Using the Node.js Test Runner and mongodb-memory-server

    How to Write Tests Using the Node.js Test Runner and mongodb-memory-server

    February 13, 2025

    I recently migrated some tests from Jest to the Node.js test runner in two of my projects that use MongoDB. In one of those projects, test runtime was reduced from 107 seconds to 25 seconds (screenshot below). In the other project, test runtime was reduced by about 66%.

    76% reduction in time taken to run tests in Jest vs Node.js test runner

    I decided to share with you how I was able to implement this. I think you’ll find it helpful, as it’s more cost-effective (in terms of reducing money spent on running tests in CI/CD), and it also improves your developer experience.

    Table of Contents

    • Prerequisites

    • The Node.js Test Runner

    • MongoDB In-Memory Server

    • How to Write the Tests

      • 1. Set Up the Project

      • 2. Set up Mongoose Schema

      • 3. Set Up Services

      • 4. Set Up Tests

      • 5. Write Tests

      • 6. Pass Tests

      • 7. Use TypeScript (Optional)

    • Conclusion

    Prerequisites

    To follow along with this guide, you should have experience working with Node.js, MongoDB, and Mongoose (or any other MongoDB object data mapper). You should also have Node.js (at least v20.18.2) and MongoDB installed on your computer.

    The Node.js Test Runner

    The Node.js test runner was introduced as an experimental feature in version 18 of Node.js. It became fully available in version 20. It gives you the ability to:

    1. Run tests

    2. Report test results

    3. Report test coverage (still experimental at version 23)

    It’s a good idea to use the in-built test runner when writing tests in Node.js because it means that you have to use fewer external dependencies. You don’t need to install an external library (and its peer dependencies) to run tests.

    The built-in best runner is also faster. Based on my experience using it on two projects (which formerly used Jest), I saw improvements of at least a 66% reduction in the time taken to run tests completely.

    And unlike other testing frameworks or libraries, the Node.js test runner was built specifically for Node.js projects. It doesn’t try to accommodate the specifics of other programming environments like the browser. The specifics of Node.js are its main and only priority.

    MongoDB In-Memory Server

    For tests that involve making requests to a database, some developers prefer to mock the requests to avoid making requests to a real database. They do this because making a request to a real database requires a lot of setting up which can cost time and resources.

    Writing and fetching data using a real database is slower compared to writing and fetching data from memory. When running automated tests, using a real MongoDB server will be slower than using an in-memory database server, and that is where mongodb-memory-server becomes useful.

    Comparison between memory and database communication with CPU

    According to its documentation, mongodb-memory-server creates and starts a real MongoDB server programmatically from within Node.js, but uses an in-memory database by default. It also allows you to connect to the database server it creates using your preferred object data mapper such as Mongoose, Prisma, or TypeORM. In this guide, we’ll use Mongoose (v8.9.6).

    Since the data stored by mongodb-memory-server resides in memory by default, it’s faster to read from and write to than when using a real database. mongodb-memory-server is also easier to set up. These benefits make it a good choice for using it as a database server for writing tests.

    Note: Make sure to install v9.1.6 of mongodb-memory-server to follow this guide. v10 currently has issues with cleaning up resources after tests are done. See this issue titled Node forking will include any –import from the original command.

    The issue has been resolved at the time of writing this article, but the fix has not been merged for installs.

    How to Write the Tests

    Now I’ll take you through the following steps to get you started writing tests:

    1. Set up the project

    2. Set up mongoose schema

    3. Set up services

    4. Set up tests

    5. Write tests

    6. Pass tests

    7. Use TypeScript (Optional)

    1. Set Up the Project

    I created a GitHub repository to make it easier for you to follow this guide. Clone the repository at nodejs-test-runner-mongoose and checkout branch 01-setup.

    In 01-setup, the dependencies for the project are in the package.json file. Install the dependencies using the npm install command to set up the project. To make sure that the setup is complete and correct, run the node . command in the terminal of your project. You should see your version of Node.js as an output on the terminal.

    # install dependencies
    npm install
    ...
    # run the node command
    node .
    # the output
    You are running Node.js v22.13.1
    

    2. Set up Mongoose Schema

    We’ll set up the schema for two collections (Task and User) in branch 02-setup-schema using Mongoose. The task/model.mjs and user/model.mjs files contain the schema for the Task and the User collection, respectively. We’ll also set up a database connection in index.mjs to ensure that the schema setup works correctly.

    I won’t go into detail about Mongoose models and schema in this article because they are outside its scope.

    When you run the node . command after implementing the changes in 02-setup-schema, you should see a similar result in the console as in the snippet below:

    node .
    You are running Node.js v22.13.1
    Created user with id 679f1d7f73fbeaf23b2007df
    Created task "Task title" for user with id "679f1d7f73fbeaf23b2007df"
    

    You can see the differences between 01-setup and 02-setup-schema via the 01-setup <> 02-setup-schema diff on GitHub.

    3. Set Up Services

    Next, we create service files (task/service.mjs and user/service.mjs) in branch 03-setup-services. Both files currently contain empty functions that we’ll write tests for later. These functions will contain business logic and also communicate with the database. We’re using JSDoc comments for typing parameters and return values.

    Click 02-setup-schema <> 03-setup-services diff to see the code changes between 02-setup-schema and 03-setup-services.

    4. Set Up Tests

    In branch 04-set-up-tests, we set up the codebase to run tests. We create test.setup.mjs which contains code that will be run before each test file is executed.

    In test.setup.mjs, the connect function creates a MongoDB In-Memory server and connects to it with Mongoose for running the tests. The closeDatabase function closes the database connection and cleans up all resources to free memory.

    The connect and closeDatabase functions get executed in the t.before hook and the t.after hook respectively. This ensures that, before a test file is run, a database connection is established through t.before. Then after tests for the file have been completely run, the database connection is dropped and the resources used are cleared up through t.after.

    In package.json, we’ll update the npm test script to node --test --import ./test.setup.mjs. This command ensures that the test.setup.mjs ES Module is preloaded and executed through the –import CLI command before each test file is run.

    Then we’ll create the test files with empty tests in the __tests__ folders for user and task. After implementing the new changes in 04-set-up-tests, running the test script with npm run test should display output similar to the snippet below:

    npm run test
    
    > nodejs-test-runner-mongoose@1.0.0 test
    > node --test --import ./test.setup.mjs
    
    ...
    
    ℹ tests 8
    ℹ suites 5
    ℹ pass 8
    ℹ fail 0
    ℹ cancelled 0
    ℹ skipped 0
    ℹ todo 0
    ℹ duration_ms 941.768873
    

    All tests currently pass because there are no assertions that fail in them. We’ll write tests with assertions in the following section.

    5. Write Tests

    Now it’s time to write tests for the functions in the service files in the 05-write-tests branch. We’re using the Node.js assert library to ensure that values returned from the functions are what we expect. You can view the tests we’ve written when you compare the differences between 04-set-up-tests and 05-write-tests

    When the tests script is run, all tests fail because we haven’t written the functions in the service files yet. You should see output similar to the snippet below when you run the test script:

    npm run test
    
    > nodejs-test-runner-mongoose@1.0.0 test
    > node --test --import ./test.setup.mjs
    
    ...
    
    ℹ tests 8
    ℹ suites 5
    ℹ pass 0
    ℹ fail 8
    ℹ cancelled 0
    ℹ skipped 0
    ℹ todo 0
    ℹ duration_ms 1202.031961
    

    6. Pass Tests

    In 06-pass-tests, we write the functions in the service files to pass the tests. Only 6 out of 7 tests pass when the test script is run because we skipped the test for the getById function in user/service.mjs has with t.skip. We haven’t finished the getById function in user/service.mjs. I figured we could leave it as an exercise.

    When you run the test script, you should get a similar output in the terminal as below:

    ℹ tests 7
    ℹ suites 4
    ℹ pass 6
    ℹ fail 0
    ℹ cancelled 0
    ℹ skipped 1
    ℹ todo 0
    ℹ duration_ms 1287.564918
    

    You can see the code we wrote to pass tests in the code changes between 05-write-tests and 06-pass-tests.

    7. Use TypeScript (Optional)

    If you intend to run tests with TypeScript, you can checkout branch 07-with-typescript. You need to have Node.js >=v22.6.0 installed because we’re using the --experimental-strip-types option in the test. To set up tests to run with TypeScript, go through the following steps:

    1. Install TypeScript using the npm install typescript --save-dev command

    2. Install tsx using the npm install tsx command

    3. Create a default tsconfig.json file at the root of the project using the npx tsc --init command

    In package.json, update the test script to this:

    "test": "node --test --experimental-strip-types --import tsx --import ./test.setup.mjs"
    
    • --experimental-strip-types helps strip out types before each test file is executed.

    • Preloading tsx with the --import helps execute the TypeScript file. Without it, the test runner will not be able to find files imported without the .ts extension. For example, user/model.ts imported with the code snippet below will not be found.

        import { UserModel } from "./model";
      

    The rest of the changes from 06-pass-tests to 07-with-typescript involve updating types, changing file extensions from .mjs to .ts and updating import statements.

    Conclusion

    In this guide, you have learned how to use the built-in Node.js test runner and why it’s often a better choice over other testing libraries and frameworks. You have also learned how to use mongodb-memory-server as a replacement for a real MongoDB server, as well as why it’s a good idea to use this instead of a real MongoDB server for tests.

    Most importantly, you have learned how to set up and run tests in Node.js using the Node.js test runner and mongodb-memory-server. You should now know how to set up your projects to run the tests if you use TypeScript.

    If you find the nodejs-test-runner-mongoose repository useful, kindly give it a star. It encourages me. Thank you.

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleLearn A-Level Computer Science Concepts
    Next Article Monster Hunter Wilds is already having a discount ahead of launch – Here’s where you can hunt for Capcom’s biggest game of 2025 at a cheaper price

    Related Posts

    Artificial Intelligence

    Markus Buehler receives 2025 Washington Award

    June 1, 2025
    Artificial Intelligence

    LWiAI Podcast #201 – GPT 4.5, Sonnet 3.7, Grok 3, Phi 4

    June 1, 2025
    Leave A Reply Cancel Reply

    Hostinger

    Continue Reading

    Mozilla is so out of Pocket for shutting down one of my favorite apps

    News & Updates

    Extract and migrate data from nested tables with user-defined nested types from Oracle to PostgreSQL

    Databases

    RansomHub Group Deploys New EDR-Killing Tool in Latest Cyber Attacks

    Development

    Create a unit testing framework for PostgreSQL using the pgTAP extension

    Databases

    Highlights

    Substrate closes $8M round to build API to accelerate AI deployment

    June 21, 2024

    Substrate Labs, an AI infrastructure startup founded by a team from Stripe, Pulumi, and Robust Intelligence, announced an…

    Beyond Threat Detection – A Race to Digital Security

    May 31, 2024

    Klein ISD Student Faces Felony Charge for Cyberattack Disrupting State Testing for 24,000 Students

    May 30, 2024

    Top GitHub Repositories Every CTO Should Keep an Eye On

    May 9, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.