Testing Strategies
Routing misconfigurations are the most common microfrontends problem. A wrong path pattern can send users to 404 pages. Tests catch these before deployment.
Outcome
Write routing validation tests using @vercel/microfrontends/next/testing utilities.
The Problem: Configuration Drift
As your application grows, routing changes:
- New paths added to apps
- Middleware matchers updated
- Redirects added or removed
Without tests, these changes can break routing silently. A redirect in marketing that conflicts with a docs path? You won't know until users complain.
Testing Utilities
The @vercel/microfrontends package includes three test utilities:
| Utility | Purpose |
|---|---|
validateRouting | Verify paths route to correct apps |
validateMiddlewareConfig | Ensure middleware matchers work with routing |
validateMiddlewareOnFlaggedPaths | Test feature flag routing behavior |
Fast Track
- Install Jest in the marketing app
- Write routing validation tests
- Add middleware configuration tests
- Run tests in CI
Hands-on Exercise 3.2
Add routing tests to the Acme Platform.
Part 1: Set Up Jest
Add Jest to the marketing app (where microfrontends.json lives):
cd apps/marketing
pnpm add -D jest @types/jest ts-jestCreate apps/marketing/jest.config.js:
/** @type {import('jest').Config} */
const config = {
testEnvironment: "node",
transform: {
"^.+\\.tsx?$": ["ts-jest", { useESM: true }],
},
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/$1",
},
testMatch: ["**/__tests__/**/*.test.ts"],
};
module.exports = config;Add test script to apps/marketing/package.json:
{
"scripts": {
"dev": "next dev --port 3000",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest"
}
}Part 2: Write Routing Tests
Create apps/marketing/__tests__/routing.test.ts:
/* @jest-environment node */
import { validateRouting } from "@vercel/microfrontends/next/testing";
describe("microfrontends routing", () => {
const configPath = "./microfrontends.json";
test("routes marketing paths to marketing app", () => {
expect(() =>
validateRouting(configPath, {
marketing: ["/", "/pricing", "/about", "/contact"],
})
).not.toThrow();
});
test("routes docs paths to docs app", () => {
expect(() =>
validateRouting(configPath, {
docs: [
"/docs",
"/docs/getting-started",
"/docs/api",
"/docs/api/reference",
"/docs/guides/setup",
],
})
).not.toThrow();
});
test("routes dashboard paths to dashboard app", () => {
expect(() =>
validateRouting(configPath, {
dashboard: [
"/app",
"/app/projects",
"/app/projects/123",
"/settings",
"/settings/profile",
"/settings/billing",
],
})
).not.toThrow();
});
test("404 paths fall through to default app", () => {
expect(() =>
validateRouting(configPath, {
marketing: ["/unknown-page", "/random/nested/path"],
})
).not.toThrow();
});
});Part 3: Write Middleware Configuration Tests
Create apps/marketing/__tests__/middleware.test.ts:
/* @jest-environment node */
import { validateMiddlewareConfig } from "@vercel/microfrontends/next/testing";
import { config as marketingMiddlewareConfig } from "../middleware";
describe("middleware configuration", () => {
const configPath = "./microfrontends.json";
test("marketing middleware config is compatible with microfrontends", () => {
expect(() =>
validateMiddlewareConfig(marketingMiddlewareConfig, configPath)
).not.toThrow();
});
});This test ensures your middleware's matcher configuration doesn't conflict with microfrontends routing.
Part 4: Run the Tests
cd apps/marketing
pnpm testExpected output:
PASS __tests__/routing.test.ts
microfrontends routing
✓ routes marketing paths to marketing app (15 ms)
✓ routes docs paths to docs app (3 ms)
✓ routes dashboard paths to dashboard app (2 ms)
✓ 404 paths fall through to default app (2 ms)
PASS __tests__/middleware.test.ts
middleware configuration
✓ marketing middleware config is compatible with microfrontends (8 ms)
Test Suites: 2 passed, 2 total
Tests: 5 passed, 5 total
Catching Misconfigurations
What happens when routing is wrong?
Add a failing test to see the error:
test("EXAMPLE: this would catch a misconfiguration", () => {
expect(() =>
validateRouting("./microfrontends.json", {
// Wrong! /docs should route to docs, not marketing
marketing: ["/docs"],
})
).toThrow();
});The error message shows exactly what's wrong:
Error: Path "/docs" routes to "docs" but expected "marketing"
Adding Tests to CI
Update turbo.json to include tests:
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"test": {
"dependsOn": ["^build"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^lint"]
}
}
}Add root-level test script to package.json:
{
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
"test": "turbo test",
"lint": "turbo lint"
}
}Now pnpm test runs tests across all apps.
Commit
git add -A
git commit -m "test: add microfrontends routing validation tests"Done-When
- Jest configured in marketing app
- Routing tests pass for all three apps
- Middleware configuration test passes
- Tests can run via
pnpm testfrom root
Test Coverage Strategy
| What to Test | Why |
|---|---|
| All known paths | Ensure routing doesn't break |
| Nested paths | Verify wildcard patterns work |
| Edge cases (404s) | Confirm fallback behavior |
| Middleware matchers | Prevent matcher conflicts |
| Feature flag paths | Validate conditional routing |
What's Next
Debug headers and tracing for observing routing decisions in production.
Was this helpful?