🌍 NodeJS · subject

NodeJS Testing Syllabus

The Testing syllabus for NodeJS in full: 3 chapters and 7 topics, every one listed below, plus 50 Testing flashcards with answers.

3Chapters
7Topics
50Flashcards

Testing syllabus: all 3 chapters

Expand any chapter to see its topics and sub-topics.

  1. Unit Testing

    3 topics
    • Mocha
    • Chai
    • Jest
  2. Integration Testing

    2 topics
    • Supertest
    • Sinon
  3. End-to-End Testing

    2 topics
    • Puppeteer
    • Cypress

NodeJS Testing flashcards — 50 questions with answers

  1. What is Mocha in the Node.js ecosystem?

    Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser. It provides the test structure (describe/it), runs tests serially, and reports results, but is assertion-library and mock agnostic (you pair it with Chai, Sinon, etc.).

  2. In Mocha, what are the roles of describe() and it()?

    describe() groups related tests into a suite (and can be nested), while it() defines an individual test case (spec). The first argument is a description string; the second is a callback containing the test logic.

  3. List Mocha's four main hooks and when each runs.

    before() runs once before all tests in a describe block; after() runs once after all tests; beforeEach() runs before every individual test; afterEach() runs after every individual test.

  4. How do you write an asynchronous test in Mocha using the done callback?

    Pass a done argument to the it() callback and call done() when the async work finishes: it('test', (done) => { asyncFn(() => done()); }). Calling done(err) with an argument fails the test. Alternatively, return a Promise or use async/await.

  5. What does the .only and .skip modifier do in Mocha?

    describe.only/it.only restrict the run to only those marked suites/tests (exclusivity); describe.skip/it.skip mark them as pending so they are ignored. A test with no callback is also treated as pending.

  6. What is Mocha's default per-test timeout and how do you change it?

    The default timeout is 2000 ms ($2$ seconds). You override it with this.timeout(ms) inside a test/hook, via the --timeout CLI flag, or in the config. A test exceeding the timeout fails with a timeout error.

  7. What is Chai and what are its three assertion styles?

    Chai is a BDD/TDD assertion library for Node.js and the browser. Its three interfaces are: assert (classic TDD), expect (BDD chainable), and should (BDD that extends Object.prototype).

  8. Write a Chai expect assertion checking that a variable foo equals the string 'bar'.

    expect(foo).to.equal('bar'); — Chai chains language connectors (to, be, is, that) that are syntactic sugar, with equal performing a strict === comparison.

  9. In Chai, what is the difference between .equal and .deep.equal?

    .equal uses strict equality (===), so for objects/arrays it compares references. .deep.equal (or .eql) recursively compares the structure and values, so two distinct objects with identical contents are considered equal.

  10. How does the Chai should style get enabled, and what is its drawback?

    You enable it by calling chai.should() once, which extends Object.prototype with a should getter (e.g. foo.should.equal('bar'). The drawback is it fails on null/undefined values and modifies the prototype, so expect is preferred for those cases.

  11. What is Jest and who originally created it?

    Jest is an all-in-one JavaScript testing framework created by Facebook (Meta). It bundles a test runner, assertion library (expect), mocking, snapshot testing, and code coverage, requiring zero-config for many projects.

  12. What Jest matcher checks strict referential equality versus deep value equality?

    toBe(value) uses Object.is / strict equality (best for primitives and same-reference checks); toEqual(value) recursively compares object/array structure. Use toStrictEqual for also checking undefined properties and types.

  13. In Jest, how do you create a mock function and assert it was called?

    const fn = jest.fn(); then after use assert with expect(fn).toHaveBeenCalled(), toHaveBeenCalledTimes(n), or toHaveBeenCalledWith(args). jest.fn() can take an implementation, and .mockReturnValue()/.mockResolvedValue() set return behavior.

  14. What is snapshot testing in Jest and how is a snapshot updated?

    expect(value).toMatchSnapshot() serializes a value and stores it in a __snapshots__ file on first run; later runs compare against the stored snapshot and fail on differences. You update snapshots intentionally with the jest --updateSnapshot (or -u) flag.

  15. Which Jest globals correspond to Mocha's before/after hooks?

    beforeAll and afterAll run once around all tests in a describe; beforeEach and afterEach run around each test. Jest also aliases test() as it(), and describe() groups tests.

  16. How do you test that an async function rejects with an error in Jest?

    await expect(asyncFn()).rejects.toThrow('message'); (or .resolves for fulfillment). You can also use try/catch with expect.assertions(n) to guarantee the assertion executed.

  17. What is jest.mock() used for?

    jest.mock('moduleName') automatically replaces a module with an auto-mocked version whose functions return undefined; you can pass a factory as the second argument to supply a custom implementation. It is hoisted to the top of the file by Babel.

  18. What is Supertest and what problem does it solve?

    Supertest is a library for high-level HTTP assertion testing of Node.js web servers (built on superagent). It lets you make requests against an Express/HTTP app and assert on status codes, headers, and body without manually binding to a port.

  19. Write a basic Supertest assertion that a GET /users returns HTTP 200.

    await request(app).get('/users').expect(200); — request(app) wraps the app; .get() issues the request; .expect(200) asserts the status code. You can chain .expect('Content-Type', /json/) and .expect(bodyMatcher).

  20. How does Supertest integrate with test runners like Mocha or Jest?

    Supertest returns a superagent-style thenable, so you either return/await request(app)... or pass done and call .end((err,res)=>done(err)). It works with any runner because it only performs the requests and assertions; the runner reports pass/fail.

Show the other 30 Testing flashcards
  1. Why can you pass an Express app directly to Supertest without calling app.listen()?

    Supertest automatically binds the app to an ephemeral (random free) port for the duration of the request and tears it down afterward. This avoids port conflicts and means you don't manage the server lifecycle in tests.

  2. What is Sinon and what three core capabilities does it provide?

    Sinon is a standalone test-double library for JavaScript. Its three core doubles are spies (record calls), stubs (replace behavior with programmed responses), and mocks (stubs with pre-set expectations that self-verify).

  3. What is the difference between a Sinon spy and a Sinon stub?

    A spy wraps an existing function and records how it was called while still invoking the original behavior. A stub replaces the function entirely with programmable behavior (return values, throws, resolved promises), so the original is not executed.

  4. How do you make a Sinon stub return a specific value or throw an error?

    stub.returns(value) sets a return value; stub.throws(err) makes it throw; stub.resolves(value)/stub.rejects(err) for promises. You can condition on arguments with stub.withArgs(x).returns(y).

  5. What is a Sinon fake timer (sinon.useFakeTimers) used for?

    It replaces the global timer functions (setTimeout, setInterval, Date) with synthetic ones you advance manually via clock.tick(ms), letting you test time-dependent code deterministically and instantly. Always restore with clock.restore().

  6. In Sinon, what is a mock and how does it differ from a stub?

    A mock is a fake with pre-programmed expectations about how it should be called; you set expectations up front (e.g. .expects('method').once()) and then call mock.verify(), which throws if expectations were not met. A stub has no built-in verification—you assert separately.

  7. Why should you call sinon.restore() or use a sandbox in tests?

    Spies/stubs replace real methods; if not restored they leak between tests and cause false results. sinon.restore() (or sandbox.restore() in afterEach) reverts all fakes to their originals, ensuring test isolation.

  8. What is Puppeteer?

    Puppeteer is a Node.js library by Google that provides a high-level API to control headless (or headful) Chrome/Chromium (and Firefox) over the DevTools Protocol. It is used for browser automation, end-to-end testing, scraping, and PDF/screenshot generation.

  9. What are the key Puppeteer objects Browser, Page, and ElementHandle?

    Browser is a browser instance launched via puppeteer.launch(); Page represents a single tab/frame where you navigate and interact; ElementHandle is an in-page DOM element reference returned by page.$()/page.waitForSelector() for clicking, typing, etc.

  10. How do you navigate to a URL and take a screenshot in Puppeteer?

    const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); await page.screenshot({ path: 'out.png' }); await browser.close(); — goto waits for load by default; close frees the browser.

  11. In Puppeteer, what is the difference between page.evaluate() and page.$eval()?

    page.evaluate(fn) runs a function in the browser page context and returns a serializable result. page.$eval(selector, fn) selects the first matching element and passes it (plus extra args) to a function run in-page, returning its result.

  12. Why is page.waitForSelector() preferred over fixed delays in Puppeteer?

    Pages load asynchronously; waitForSelector polls until the element appears (or a timeout), making tests reliable. Fixed sleeps are flaky—too short causes failures, too long slows the suite. Puppeteer offers waitForSelector, waitForNavigation, and waitForFunction.

  13. What is headless mode in Puppeteer and how do you disable it?

    Headless mode runs Chromium without a visible UI, which is faster and suited to CI. You disable it by launching with { headless: false } to watch the browser, often combined with { slowMo: ms } to slow operations for debugging.

  14. What is Cypress and what type of testing is it primarily built for?

    Cypress is a JavaScript end-to-end (E2E) testing framework that runs tests in the same run loop as the application inside a real browser. It also supports component and integration testing, offering time-travel debugging, automatic waiting, and a visual Test Runner.

  15. How does Cypress's architecture differ from Selenium/Puppeteer?

    Cypress executes directly inside the browser alongside the app (not via a remote WebDriver/DevTools protocol over the network). This gives it native access to the DOM, network, and app internals, enabling automatic waiting and time-travel, but limits it to browsers it supports and single-origin per test historically.

  16. What does Cypress's automatic retry/waiting mechanism do?

    Cypress commands automatically retry assertions and element queries until they pass or a timeout is reached (default $4000$ ms for most commands), eliminating most manual waits/sleeps. This makes tests less flaky against asynchronous UI updates.

  17. Write a basic Cypress test that visits a page and clicks a button.

    cy.visit('/'); cy.get('button.submit').click(); — cy.visit loads the app, cy.get queries the DOM (retrying), and .click() interacts. Assertions chain via .should(), e.g. cy.get('.result').should('contain', 'Done').

  18. What is cy.intercept() used for in Cypress?

    cy.intercept() spies on and/or stubs network requests, letting you assert requests were made, wait on them with aliases (cy.wait('@alias')), and return fixture/mocked responses. It is the modern replacement for cy.route().

  19. What are Cypress fixtures?

    Fixtures are external static data files (usually JSON in the cypress/fixtures folder) loaded via cy.fixture('name'). They provide consistent mock data for stubbing network responses or seeding test input.

  20. Compare Mocha and Jest at a high level.

    Mocha is a lightweight, flexible test runner that you compose with separate assertion (Chai) and mocking (Sinon) libraries. Jest is an all-in-one framework with a built-in runner, assertions, mocking, snapshots, and coverage, plus parallel test execution and zero-config defaults.

  21. Which test framework provides its own built-in mocking, and which typically relies on Sinon?

    Jest ships with built-in mocking (jest.fn, jest.mock, jest.spyOn). Mocha has no built-in mocking, so it is commonly paired with Sinon for spies, stubs, and mocks.

  22. How do you spy on an existing object method in both Jest and Sinon?

    Jest: jest.spyOn(object, 'method') wraps the method, tracking calls while optionally calling through or being overridden with .mockImplementation(). Sinon: sinon.spy(object, 'method') does the same, and sinon.stub(object, 'method') replaces it.

  23. What is the difference between unit, integration, and end-to-end (E2E) tests, and which tools fit each?

    Unit tests isolate a single function/module (Jest, Mocha+Chai, Sinon for mocks). Integration tests verify modules working together, including HTTP layers (Supertest against Express). E2E tests drive the full app through a real browser/UI (Cypress, Puppeteer).

  24. What is TDD (Test-Driven Development) and its Red-Green-Refactor cycle?

    TDD writes tests before implementation. The cycle is: Red (write a failing test), Green (write minimal code to pass it), then Refactor (clean up code while keeping tests green). It drives design and guarantees coverage of new behavior.

  25. How is code coverage reported in Jest, and what do the metrics mean?

    Run jest --coverage (Jest uses Istanbul under the hood) to output statement, branch, function, and line coverage percentages. Coverage is roughly $\frac{\text{executed code units}}{\text{total code units}} \times 100\%$; it shows how much code the tests exercise, not correctness.

  26. What does expect.assertions(n) accomplish in Jest, and why use it in async tests?

    It asserts that exactly n assertions run during the test. In async/callback tests it guards against a test passing silently when the code path (e.g. a catch block) never executes, ensuring the expected assertions actually ran.

  27. In Chai, how do you assert that a function throws an error?

    expect(fn).to.throw(); — you pass the function reference (not fn()) so Chai can invoke it and catch. You can narrow it with expect(fn).to.throw(TypeError, /message/) to match the error type and message.

  28. What does Supertest's .expect() do when given a function argument?

    When passed a function, .expect(fn) invokes it with the response object so you can run custom assertions (e.g. throw if res.body.name !== 'John'). Throwing inside it fails the test; returning nothing passes. This complements the status/header/body overloads.

  29. What is the purpose of Sinon's sandbox (sinon.createSandbox)?

    A sandbox groups spies, stubs, mocks, and fake timers so they can all be reset/restored together with a single sandbox.restore(). This prevents fakes leaking across tests and is cleaner than restoring each double individually, typically restored in afterEach.

  30. How do headless browser tools like Puppeteer and Cypress differ in scope?

    Puppeteer is a general browser-automation library (scraping, PDFs, screenshots, testing) with a low-level Chrome DevTools API and no built-in assertions/runner. Cypress is a purpose-built testing framework with its own runner, assertions, retries, and dashboard, focused on E2E/component tests.

NodeJS Testing FAQ

What is in the NodeJS Testing syllabus?

NodeJS Testing is split into 3 chapters: Unit Testing, Integration Testing and End-to-End Testing. Together they contain 7 topics.

How many chapters are in NodeJS Testing?

3 chapters, containing 7 topics. The largest chapter is Unit Testing, with 3 topics.

Are there flashcards for NodeJS Testing?

Yes — a 50-card Testing deck, printed in full in the flashcards section of this page and available in the Examius app with spaced repetition. The free plan covers one exam of your choice, including its flashcards; Examius Pro, a one-time purchase, unlocks every other exam and deck.