top of page
Search

How to Test Node.js Microservices in a Monorepo Using Vitest + npx

  • Writer: Mark Kendall
    Mark Kendall
  • 3 days ago
  • 4 min read



🚀 How to Test Node.js Microservices in a Monorepo Using Vitest +

npx




A Practical, Modern Guide for Developers



Testing microservices inside a Node.js monorepo can feel complicated at first — different packages, shared models, middleware, controllers, and sometimes messaging systems like Kafka or RabbitMQ. But with the right structure, it becomes clean, fast, predictable, and enterprise-ready.


This guide shows you exactly how to test Node.js microservices using:


  • Vitest as the testing framework

  • npx to run local test binaries

  • Full mocking of external systems

  • Positive + negative controller testing

  • A monorepo-friendly folder structure



This article works for any company, any project, any microservice — use it everywhere.





🧩 Why Testing Microservices Requires a Different Approach



Microservices typically depend on:


  • Validation middleware

  • Business services

  • Shared models

  • Messaging systems (Kafka, RabbitMQ, SNS/SQS)

  • External HTTP/API calls

  • Databases



During unit tests, none of these should execute for real.


Good microservice testing has one goal:


Only test the logic inside the microservice — not the world around it.


This is why mocking is essential.





📁 Recommended Monorepo Folder Structure



A common layout looks like this:

/repo-root

   /packages

      /models

      /shared-libraries

      /service-A

         src/

         tests/

         package.json

      /service-B

         src/

         tests/

         package.json

Every service has:


  • Its own code

  • Its own dependencies

  • Its own test runner

  • Its own mocks



And optionally shares a model library.


This is the pattern used by Nx, Turborepo, pnpm workspaces, Yarn workspaces, and large engineering orgs.





🧪 Why Vitest Is the Best Choice for Microservices



Vitest gives you:


  • Built-in mocking

  • Native TypeScript support

  • Very fast execution

  • Jasmine/Jest-style test syntax

  • Perfect compatibility with monorepos

  • CI-friendly command line execution



It’s one of the cleanest tools for modern backend testing.





🔑 Why You Should Always Run Tests Using

npx vitest



This is one of the most important ideas in this guide.



npx

runs the

local

Vitest for that microservice



In a monorepo, each service may depend on its own version of tools.


Running:

npx vitest

guarantees:


  • You run the test runner installed for that service,

  • NOT a global version,

  • NOT another package’s version.




✔ Consistent between developers and CI



Teams struggle when:


  • Devs run global tools

  • CI runs local tools



npx eliminates that mismatch completely.



✔ Required when test suites live in multiple subdirectories



If each project has its own node_modules, npx automatically resolves the correct binary.


This is exactly how enterprise monorepos operate.





🔄 How to Run Tests in a Microservice



From inside the microservice folder:

npx vitest --run

Or in watch/development mode:

npx vitest

If using an npm/pnpm script:

{

  "scripts": {

    "test": "vitest --run"

  }

}

Then:

npm test

But npx vitest is still the cleanest for monorepo isolation.





🧱 The Golden Rule:

Mock Everything External



A proper microservice unit test never calls:


  • Kafka / RabbitMQ / SNS/SQS

  • External HTTP APIs

  • Databases

  • Auth servers

  • Cloud services

  • Other microservices

  • Validation middleware that hits outside resources



Unit tests should isolate only the code inside the microservice — nothing else.





🧪 Example Mocking Patterns



Here are common mock styles using Vitest.



✔ Mocking a middleware module


vi.mock('../middleware/validator', () => ({

  validate: vi.fn().mockReturnValue(true)

}));


✔ Mocking a messaging publisher


vi.mock('../messaging/publisher', () => ({

  publishEvent: vi.fn().mockResolvedValue({

    eventId: 'mocked-id-123'

  })

}));


✔ Mocking a service layer method


vi.mock('../services/businessService', () => ({

  process: vi.fn().mockResolvedValue({ status: 'OK' })

}));


✔ Spying on controller behavior


import { describe, it, expect, vi } from 'vitest';

import controller from '../src/controller';


describe('Controller Tests', () => {

  it('returns success response', async () => {

    const req = { body: { name: 'John' } };

    const res = { status: vi.fn().mockReturnThis(), json: vi.fn() };


    await controller(req, res);


    expect(res.status).toHaveBeenCalledWith(200);

  });

});





🌗 Positive + Negative Testing Strategy



A professional microservice test suite includes:



✔ Positive Tests (Happy Path)



  • Valid payloads

  • Successful processing

  • Valid Kafka/event output

  • Correct response codes




✔ Negative Tests (Unhappy Path)



  • Invalid payloads

  • Middleware failures

  • Missing required fields

  • Exceptions thrown from service layer

  • Edge cases



Both are essential to guarantee reliability.





🚀 Running Tests in CI/CD Pipelines



Most systems (GitHub Actions, GitLab, AWS CodeBuild, Azure DevOps) run tests like this:

script:

  - npm ci

  - npx vitest --run

This ensures:


  • Fresh node_modules

  • Reproducible test runs

  • No global dependencies

  • True monorepo isolation

  • Deterministic builds



This is EXACTLY how enterprise pipelines run Vitest inside microservices.





📘 Best Practices Summary (Copy This Everywhere)




✔ 1. Run Vitest using

npx



Guarantees you’re using the local version for that microservice.



✔ 2. Mock all external dependencies



Never hit messaging systems, databases, or external APIs.



✔ 3. Test at the microservice boundary



Focus on controllers, services, and middleware behavior.



✔ 4. Include positive and negative scenarios



Microservices must handle both gracefully.



✔ 5. Keep tests inside each service folder



Monorepos require test isolation.



✔ 6. Never rely on global installs



Everything should be self-contained.



✔ 7. CI should run

npm ci

+

npx vitest



This ensures developer/CI consistency.





🎉 Final Thoughts



Testing microservices inside a Node.js monorepo does not have to be complicated.

With Vitest + npx + proper mocking, you get:


  • Fast feedback

  • Stable builds

  • Reusable patterns across companies

  • Predictable test environments

  • CI/CD compatibility

  • Zero external dependencies



This approach scales from a single microservice to hundreds of them.




 
 
 

Recent Posts

See All
⭐ NU-KENDALLS: The Sound, the Story

⭐ NU-KENDALLS: The Sound, the Story, and the Spirit of The Mark Kendall Band By Mark Kendall — Burleson, Texas Some bands build songs. Some bands build moments. NU-KENDALLS — also known as The Mark Ke

 
 
 
Do I Still Need Website Traffic in the Age of AI?

Do I Still Need Website Traffic in the Age of AI? A Pepperdine Architect’s Lighthearted Take on Influence, Indexing & Being “Real” in 2025 By Mark Kendall — LearnTeachMaster.org Introduction: When “Be

 
 
 

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
Post: Blog2_Post

Subscribe Form

Thanks for submitting!

©2020 by LearnTeachMaster DevOps. Proudly created with Wix.com

bottom of page