Overview

36 Testing your application

This chapter emphasizes that maintaining a production Node.js application means constantly guarding against regressions as new code is introduced. It introduces testing as the primary safeguard, outlining the essentials of a good test: representative data, clear expectations, and a framework to execute and report results. You begin with high-level goals—protect existing behavior, provide a shared contract for teams, and anticipate edge cases—and get a practical roadmap for building a reliable test suite that covers functions, controllers, models, and APIs.

The lesson starts with quick wins using Node’s built-in assert module to express simple equality and inequality checks, then expands to a modern workflow with Mocha (test runner) and Chai (assertion library). You learn Mocha’s structure with describe blocks for grouping and it blocks for individual expectations, and Chai’s expect style for expressive assertions. A concrete example tests a controller utility that shapes request data, showing how to organize tests in a dedicated test directory, run them via the mocha command, and use deep comparisons for object structures.

Next, the chapter demonstrates integrated testing with a database and server to mimic real execution. By setting NODE_ENV to test, the app can connect to a separate test database and port, exporting the app for use by tests. With chai-http, tests make HTTP requests against the running server to validate controller actions, while model tests use hooks (such as beforeEach) to isolate cases, save documents, and assert persisted state. Together, these patterns deliver end-to-end confidence—from verifying Mongoose saves to checking that GET /users returns a 200—helping teams catch edge cases early and reduce production failures.

Displaying passing tests in terminal

FAQ

Why should I add tests to my Node.js application?Tests help prevent regressions when new code is added or existing code is changed. They codify expected behavior so multiple developers can modify features with confidence.
What is an assertion test?An assertion test expresses an expectation about values or outcomes (for example, comparing function output to an expected result) and reports a failure when the expectation isn’t met.
How do I write a basic test with Node’s assert module?Require the assert module and compare values with functions like assert.equal or assert.notEqual. Run the file with node to see pass/fail results. This is useful for quick, low-overhead checks.
What are Mocha and Chai, and why use both?Mocha is a test runner that structures and executes tests. Chai is an assertion library that provides expect/should/assert styles to state outcomes. Together they let you describe tests and verify results clearly.
What’s the difference between describe and it in Mocha?describe groups related tests for a module or function, improving organization and output. it contains an individual test with specific expectations.
How do I set up and run a Mocha test suite?Create a test folder at the project root and place spec files there (for example, usersControllerSpec.js). Install Mocha, then run mocha in the project directory. Mocha auto-discovers tests in the test folder.
How do I test routes/controllers with a running server?Use chai-http with Chai. Require your app, enable chai.use(chaiHttp), then call chai.request(app).get('/route'). In the callback, assert on status codes, response bodies, and errors.
How do I configure a separate test environment (DB and port)?Set process.env.NODE_ENV = 'test' in test files. In your app, switch DB URI and server port based on NODE_ENV (for example, use a test database and a non-default port like 3001) to avoid touching development/production data.
How do I test Mongoose models safely and handle async code?Clear test collections in a beforeEach hook so tests don’t affect each other. Save documents, query results, and use Chai expectations (for example, length checks and presence of _id). Call done (or return Promises/async functions) to finish async tests.
What is test-driven development (TDD) and how would I apply it?TDD means writing failing tests first, implementing the minimal code to pass them, and then rerunning until green. For example, write a test for reverse('Hello') → 'olleH', run and see it fail, implement reverse, and iterate until it passes.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Get Programming with Node.js ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Get Programming with Node.js ebook for free