惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
S
Security @ Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
Simon Willison's Weblog
Simon Willison's Weblog
P
Proofpoint News Feed
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Palo Alto Networks Blog
L
LINUX DO - 最新话题
The Last Watchdog
The Last Watchdog
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
Attack and Defense Labs
Attack and Defense Labs
C
Cybersecurity and Infrastructure Security Agency CISA
GbyAI
GbyAI
Hacker News: Ask HN
Hacker News: Ask HN
W
WeLiveSecurity
Spread Privacy
Spread Privacy
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tor Project blog
Y
Y Combinator Blog
S
Schneier on Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
Latest news
Latest news
F
Fortinet All Blogs
C
Cisco Blogs
Scott Helme
Scott Helme
Recorded Future
Recorded Future
T
Tailwind CSS Blog
博客园_首页
V
Visual Studio Blog
The Cloudflare Blog
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
L
LINUX DO - 热门话题
量子位
Last Week in AI
Last Week in AI
D
DataBreaches.Net
M
MIT News - Artificial intelligence
小众软件
小众软件
Hacker News - Newest:
Hacker News - Newest: "LLM"
F
Full Disclosure
IT之家
IT之家
The Register - Security
The Register - Security
U
Unit 42
S
Security Affairs
WordPress大学
WordPress大学
H
Hacker News: Front Page
Cloudbric
Cloudbric

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Unit Test AI Guide — Zero Hallucination, Cross-Stack Standard
Bhaumik · 2026-06-19 · via DEV Community

Focus: Unit Tests ONLY — no integration, no E2E

Stacks: Node.js (NestJS/Express) · React.js · Python · Angular · Laravel

Goal: AI generates unit tests consistently, deterministically, without hallucination

IDE: Cursor (Primary) + Claude (Secondary)


Part 1 — Best Single Library Per Stack (Final Decision)

Do not mix libraries. Pick one per stack, configure it fully, never deviate.

| Stack | Library | Why This One |

|---|---|---|

| Node.js / NestJS / Express | Jest | Native DI mocking, @nestjs/testing built around it, widest ecosystem |

| React.js | Vitest + @testing-library/react | Native Vite/ESM support, Jest-compatible API, 3–10x faster |

| Python | pytest | De facto standard, fixture system eliminates boilerplate, best plugin ecosystem |

| Angular | Jest (replace Karma) | Karma is deprecated in Angular 17+; Jest is the official migration target |

| Laravel | Pest | Modern syntax, built on PHPUnit, higher signal-to-noise ratio |

Rule: If someone suggests a second library for the same stack, reject it. One library per stack, configured once, followed always.


Part 2 — IDE: Cursor (Only Choice for This Goal)

Why Cursor and Not VS Code / WebStorm

| Capability | Cursor | VS Code + Copilot | WebStorm |

|---|---|---|---|

| Project-level AI rules | ✅ .cursor/rules/ | ❌ | ❌ |

| Codebase-aware context | ✅ @codebase | Partial | Partial |

| Run terminal + read output | ✅ Composer | ❌ | ❌ |

| Multi-file generation | ✅ Agent mode | Limited | ❌ |

| Custom instructions per filetype | ✅ | ❌ | ❌ |

| MCP server integration | ✅ | ❌ | ❌ |

Cursor's .cursor/rules/ system is the only IDE-native mechanism that injects persistent, project-scoped instructions into every AI interaction — this is what prevents hallucination at the source.

Cursor Setup for This Project



project-root/


├── .cursor/


│   └── rules/


│       ├── unit-test-global.mdc       ← applies to all files


│       ├── unit-test-nestjs.mdc       ← applies to *.service.ts, *.guard.ts


│       ├── unit-test-react.mdc        ← applies to *.tsx, *.component.tsx


│       ├── unit-test-python.mdc       ← applies to *.py


│       ├── unit-test-angular.mdc      ← applies to *.component.ts, *.service.ts


│       └── unit-test-laravel.mdc      ← applies to *Service.php, *Model.php


├── CLAUDE.md                          ← Claude project memory file


└── ...



Part 3 — Cursor Rules Files (Anti-Hallucination Core)

These files are injected into every AI prompt automatically when working on matching files.

3.1 Global Unit Test Rule

File: .cursor/rules/unit-test-global.mdc



---


description: Global unit test rules — applies to all files in this project


globs: ["**/*.spec.ts", "**/*.test.ts", "**/*.spec.tsx", "**/*_test.py", "**/Test*.php"]


alwaysApply: true


---





# Unit Test Contract — MUST FOLLOW, NO EXCEPTIONS





## What is a unit test here


- Tests ONE class or function in complete isolation


- ALL external dependencies are mocked — no real DB, no real HTTP, no real file system


- Each test runs independently — no shared mutable state between tests


- Runs in < 100ms





## Structure: AAA — Always, Without Exception


Every test MUST have these three sections, with comments:


// Arrange — set up inputs, mocks, expected values

// Act — call the single function/method under test

// Assert — verify exactly one outcome






## Naming Convention — Mandatory


- File: `[module-name].spec.ts` or `[module-name].unit.spec.ts`


- Describe block: exact class or function name


- It/test block: "should [expected behavior] when [specific condition]"


  GOOD: "should throw NotFoundException when user does not exist"


  BAD:  "user not found", "test 1", "works correctly"





## What to test per function — minimum coverage


1. Happy path — valid input → expected output


2. Null/undefined input — how does it fail safely


3. Empty input — empty string, empty array, zero


4. Error path — when dependency throws, what happens


5. Boundary — max length, negative numbers, boolean edge





## What NOT to include in unit tests


- Database queries (mock the repository)


- HTTP calls (mock the service/axios/fetch)


- File system operations (mock fs)


- Timer behavior (use jest.useFakeTimers)


- Random values (mock Math.random or faker with fixed seed)





## AI Instruction


When asked to generate a unit test:


1. READ the function signature and types first


2. IDENTIFY all dependencies (constructor args, imported modules)


3. MOCK every dependency — never use real implementations


4. Generate minimum 4 test cases per method (happy, null, error, edge)


5. NEVER import from test doubles or assume what isn't in the source file


6. If you are unsure of a type — ASK, do not assume



3.2 NestJS Rule

File: .cursor/rules/unit-test-nestjs.mdc



---


description: NestJS unit test rules


globs: ["src/**/*.service.ts", "src/**/*.guard.ts", "src/**/*.interceptor.ts", "src/**/*.pipe.ts"]


---





# NestJS Unit Test Rules





## Library: Jest + @nestjs/testing + jest-mock-extended





## Always use Test.createTestingModule



typescript

const module = await Test.createTestingModule({

providers: [

SubjectService,


{ provide: DependencyService, useValue: mockDependency }

]

}).compile();






## Mock Pattern — jest-mock-extended



typescript

import { createMock } from '@golevelup/ts-jest';

// OR

import { mock } from 'jest-mock-extended';

const mockUserRepo = mock();






## Never


- Never use `new SubjectService()` directly — always use TestingModule


- Never let `useValue` contain real implementations


- Never test more than one service per describe block





## Repository Mock Template



typescript

const mockRepo = {

findOne: jest.fn(),

save: jest.fn(),

delete: jest.fn(),

findAll: jest.fn(),

update: jest.fn(),

};






## Required imports for every NestJS spec file



typescript

import { Test, TestingModule } from '@nestjs/testing';

import { NotFoundException, BadRequestException } from '@nestjs/common';




markdown


3.3 React Rule

File: .cursor/rules/unit-test-react.mdc



---


description: React unit test rules


globs: ["src/**/*.tsx", "src/**/*.component.tsx", "src/hooks/**/*.ts"]


---





# React Unit Test Rules





## Library: Vitest + @testing-library/react + @testing-library/user-event





## Required setup in vitest.config.ts



typescript

export default defineConfig({

test: {

environment: 'jsdom',


globals: true,


setupFiles: ['./src/test/setup.ts']

}

})






## setup.ts



typescript

import '@testing-library/jest-dom';






## Component test structure



typescript

import { render, screen } from '@testing-library/react';

import userEvent from '@testing-library/user-event';

import { vi } from 'vitest';






## Mocking rules for React


- Mock ALL hooks that call APIs: `vi.mock('../hooks/useUsers')`


- Mock ALL context providers — wrap with test-specific providers


- Mock router: use `MemoryRouter` from react-router-dom


- NEVER mock internal state (useState) — test behavior, not implementation





## Query priority (RTL best practice — mandatory)


1. getByRole — prefer always


2. getByLabelText — for forms


3. getByText — for content


4. getByTestId — LAST RESORT only, requires data-testid attribute





## User event — always use userEvent, never fireEvent



typescript

const user = userEvent.setup();

await user.click(button);

await user.type(input, 'value');






## Custom hook testing



typescript

import { renderHook, act } from '@testing-library/react';

const { result } = renderHook(() => useMyHook());

act(() => result.current.doSomething());

expect(result.current.value).toBe('expected');




typescript


3.4 Python Rule

File: .cursor/rules/unit-test-python.mdc



---


description: Python unit test rules


globs: ["**/*.py", "!**/*migrations*"]


---





# Python Unit Test Rules





## Library: pytest + pytest-mock + factory-boy





## File naming


- Source: `app/services/user_service.py`


- Test:   `tests/unit/test_user_service.py`


- ALWAYS mirror the source directory structure under tests/unit/





## Class under test — always use dependency injection



python

GOOD — injectable dependency

class UserService:

def __init__(self, repo: UserRepository):


    self.repo = repo

BAD — untestable

class UserService:

def __init__(self):


    self.repo = UserRepository()  # can't mock this






## Mock pattern — pytest-mock (mocker fixture)



python

def test_raises_when_user_not_found(mocker):

mock_repo = mocker.Mock()


mock_repo.find_by_id.return_value = None


service = UserService(mock_repo)


with pytest.raises(UserNotFoundException):


    service.get_user("missing-id")






## Async tests — pytest-asyncio



python

import pytest

@pytest.mark.asyncio

async def test_async_service(mocker):

mock_repo = mocker.AsyncMock()


...






## Fixture pattern — for shared setup



python

@pytest.fixture

def user_service(mocker):

repo = mocker.Mock()


return UserService(repo), repo

def test_get_user_happy_path(user_service):

service, repo = user_service


repo.find_by_id.return_value = User(id="1", email="a@b.com")


result = service.get_user("1")


assert result.email == "a@b.com"






## Naming


- File: `test_[module_name].py`


- Function: `test_[expected_behavior]_when_[condition]`



markdown


3.5 Angular Rule

File: .cursor/rules/unit-test-angular.mdc



---


description: Angular unit test rules


globs: ["src/app/**/*.component.ts", "src/app/**/*.service.ts", "src/app/**/*.pipe.ts", "src/app/**/*.guard.ts"]


---





# Angular Unit Test Rules





## Library: Jest (NOT Karma — Karma is deprecated Angular 17+)





## Migration from Karma to Jest (one-time)



bash

ng add @angular-builders/jest






## TestBed configuration — always minimal



typescript

await TestBed.configureTestingModule({

imports: [ComponentUnderTest], // standalone components

providers: [

{ provide: UserService, useValue: mockUserService }

]

}).compileComponents();






## Service mock pattern



typescript

const mockUserService = {

getUser: jest.fn(),

createUser: jest.fn(),

};






## Component test — check DOM behavior, not internal state



typescript

fixture.detectChanges(); // trigger ngOnInit

const button = fixture.debugElement.query(By.css('[data-testid="submit"]'));

button.nativeElement.click();

fixture.detectChanges();

expect(fixture.debugElement.query(By.css('.error-msg'))).toBeTruthy();






## Pipe test — pure function, no TestBed needed



typescript

it('should transform date correctly', () => {

const pipe = new DateFormatPipe();

expect(pipe.transform(new Date('2024-01-01'))).toBe('Jan 1, 2024');

});






## Guard/resolver test — inject and call directly



typescript

const guard = TestBed.inject(AuthGuard);

const result = await guard.canActivate(mockRoute, mockState);

expect(result).toBe(false);




python


3.6 Laravel Rule

File: .cursor/rules/unit-test-laravel.mdc



---


description: Laravel unit test rules


globs: ["app/Services/**/*.php", "app/Models/**/*.php", "app/Http/Requests/**/*.php", "app/Actions/**/*.php"]


---





# Laravel Unit Test Rules





## Library: Pest (NOT PHPUnit directly — Pest wraps it with better syntax)





## File location


- Source: `app/Services/UserService.php`


- Test:   `tests/Unit/Services/UserServiceTest.php`





## Class under test — use constructor injection



php

class UserService {

public function __construct(


    private readonly UserRepositoryInterface $repo


) {}

}






## Mock pattern — Mockery (included with Pest/PHPUnit)



php

it('throws exception when user not found', function () {

// Arrange


$repo = Mockery::mock(UserRepositoryInterface::class);


$repo->shouldReceive('findById')->once()->andReturn(null);


$service = new UserService($repo);





// Act & Assert


expect(fn () => $service->getUser('abc'))


    ->toThrow(UserNotFoundException::class);

});






## Data provider pattern (Pest datasets)



php

it('validates email format', function (string $email, bool $valid) {

expect(validateEmail($email))->toBe($valid);

})->with([

['valid@email.com', true],


['notanemail', false],


['', false],


['@nodomain.com', false],

]);






## What NOT to do in unit tests


- Never call $this->get() or $this->post() — that is feature testing


- Never use RefreshDatabase — that is feature/integration testing


- Never resolve from service container — inject directly



markdown


Part 4 — CLAUDE.md (Claude Project Memory)

Place this at project root. Claude reads it on every session automatically.

File: CLAUDE.md



# Project: [Your Project Name]


# Claude Unit Test Instructions





## Stack


- Backend: NestJS + TypeScript


- Frontend: React + Vite + TypeScript


- Testing: Jest (NestJS) + Vitest (React) + Pest (Laravel) + pytest (Python)





## Unit Test Rules — NON-NEGOTIABLE





### When asked to generate a unit test:


1. NEVER generate integration or E2E tests unless explicitly asked


2. ALWAYS mock every external dependency


3. ALWAYS follow AAA (Arrange-Act-Assert) with comments


4. ALWAYS generate minimum 4 cases: happy path, null/empty, error thrown, edge case


5. NEVER use `any` type in TypeScript tests


6. NEVER leave `TODO` comments in generated tests





### Naming


- NestJS: `[name].service.spec.ts` inside same directory as source


- React: `[ComponentName].test.tsx` inside `__tests__/` or same directory


- Python: `test_[module].py` under `tests/unit/`


- Laravel: `[Name]Test.php` under `tests/Unit/`





### Test should describe BEHAVIOR, not implementation


GOOD: "should return empty array when no users match search"


BAD: "test getUserByFilter"





### If you are unsure of the correct mock structure:


- Ask what the dependency interface looks like


- Do NOT invent method names that don't exist in the source





### Coverage target: 80% lines, 75% branches per module





## Project Structure Reference


src/


  modules/


    users/


      users.service.ts


      users.service.spec.ts   ← unit test lives here


      users.repository.ts


      users.repository.spec.ts



Part 5 — MCP Servers for Unit Testing in Cursor + Claude

MCP (Model Context Protocol) servers extend AI capabilities. For unit testing, these are the relevant ones:

5.1 Filesystem MCP (Built-in Cursor — use directly)

Cursor already has filesystem access. No extra MCP needed to read source files and generate tests. The .cursor/rules/ system handles this.

5.2 Available MCP Servers for Testing Workflows

1. @executeautomation/playwright-mcp-server

  • Scope: E2E only — not relevant for unit tests

  • Skip for this use case

2. @modelcontextprotocol/server-filesystem

  • Gives Claude access to project files

  • Use in Claude Desktop to read source → generate tests

  • Install: configured in claude_desktop_config.json

3. Custom Testing MCP (Build This — Highest Value)

Build a lightweight MCP server that:

  • Reads a source file

  • Extracts function signatures + types

  • Returns structured JSON to Claude

  • Claude generates tests from structure, not guesswork



// mcp-test-generator/src/index.ts


import { Server } from '@modelcontextprotocol/sdk/server/index.js';


import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';


import * as ts from 'typescript';





const server = new Server({ name: 'test-generator', version: '1.0.0' }, {


  capabilities: { tools: {} }


});





server.setRequestHandler('tools/call', async (req) => {


  if (req.params.name === 'extract_signatures') {


    const { filePath } = req.params.arguments;


    const signatures = extractFunctionSignatures(filePath); // parse AST


    return { content: [{ type: 'text', text: JSON.stringify(signatures) }] };


  }


});





function extractFunctionSignatures(filePath: string) {


  // Use TypeScript compiler API to extract:


  // - class name


  // - method names


  // - parameter types


  // - return types


  // - injected dependencies (constructor params)


  const program = ts.createProgram([filePath], {});


  const sourceFile = program.getSourceFile(filePath);


  // ... AST traversal


  return { className, methods, dependencies };


}


Why this matters: When Claude receives typed signatures instead of raw source code, it cannot hallucinate — it generates tests from concrete types, not guesses.

5.3 Claude Desktop MCP Config



// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)


// %APPDATA%\Claude\claude_desktop_config.json (Windows)


{


  "mcpServers": {


    "filesystem": {


      "command": "npx",


      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/your/project"]


    },


    "test-generator": {


      "command": "node",


      "args": ["/path/to/your/mcp-test-generator/dist/index.js"]


    }


  }


}


5.4 Cursor MCP Config



// .cursor/mcp.json (project-level)


{


  "mcpServers": {


    "test-generator": {


      "command": "node",


      "args": ["./tools/mcp-test-generator/dist/index.js"]


    }


  }


}



Part 6 — Anti-Hallucination Prompt Templates

The root cause of AI hallucination in tests: AI invents method names, wrong mock structures, non-existent imports. These prompts eliminate that.

6.1 Cursor Cmd+K Prompt (Use This Exactly)



Generate a unit test file for this [NestJS service / React component / Python class / Angular service / Laravel service].





Rules:


- Library: [Jest / Vitest / pytest / Jest / Pest]


- Test only THIS file — no integration


- Mock ALL dependencies listed in the constructor/props


- Follow AAA pattern with comments


- Minimum 4 test cases per public method


- Use ONLY methods/properties that exist in this source file


- Do NOT import anything not shown in the source


- Naming: "should [behavior] when [condition]"


6.2 Claude Prompt (For CLAUDE.md aware sessions)



Read [filename].


Extract:


1. Class/function name


2. All public methods with parameter types and return types


3. All constructor dependencies (for mocking)





Then generate the unit test file following CLAUDE.md rules.


Do NOT assume any method exists unless you can see it in the source.


6.3 Batch Test Generation Prompt



For each file in [directory], generate a corresponding .spec.ts file.


Process one file at a time.


For each file:


  1. Read the source


  2. List the public methods you found (confirm before generating)


  3. Generate the test file


  4. Show the test file path





Do not proceed to the next file until the current one is confirmed.



Part 7 — Project Structure Convention

All stacks follow the same proximity principle: test file lives next to source file.

Node.js / NestJS / Angular



src/


  modules/


    users/


      users.service.ts


      users.service.spec.ts        ← unit test


      users.repository.ts


      users.repository.spec.ts     ← unit test


      users.guard.ts


      users.guard.spec.ts          ← unit test


React



src/


  components/


    UserCard/


      UserCard.tsx


      UserCard.test.tsx            ← unit test


      UserCard.stories.tsx         ← storybook (optional)


  hooks/


    useUserData.ts


    useUserData.test.ts            ← unit test


Python



app/


  services/


    user_service.py


tests/


  unit/


    services/


      test_user_service.py        ← mirrors app/ structure


Laravel



app/


  Services/


    UserService.php


tests/


  Unit/


    Services/


      UserServiceTest.php         ← mirrors app/ structure



Part 8 — CI Enforcement

All of this means nothing without enforcement. The pipeline is the final gate.

GitHub Actions — Multi-stack parallel



name: Unit Tests





on: [push, pull_request]





jobs:


  nestjs-unit:


    runs-on: ubuntu-latest


    steps:


      - uses: actions/checkout@v4


      - uses: actions/setup-node@v4


        with: { node-version: '20' }


      - run: npm ci


      - run: npm run test:unit -- --coverage --coverageThreshold='{"global":{"lines":80}}'





  react-unit:


    runs-on: ubuntu-latest


    steps:


      - uses: actions/checkout@v4


      - uses: actions/setup-node@v4


        with: { node-version: '20' }


      - run: npm ci


      - run: npx vitest run --coverage





  python-unit:


    runs-on: ubuntu-latest


    steps:


      - uses: actions/checkout@v4


      - uses: actions/setup-python@v5


        with: { python-version: '3.12' }


      - run: pip install -r requirements-dev.txt


      - run: pytest tests/unit/ --cov=app --cov-fail-under=80





  laravel-unit:


    runs-on: ubuntu-latest


    steps:


      - uses: actions/checkout@v4


      - uses: shivammathur/setup-php@v2


        with: { php-version: '8.3' }


      - run: composer install


      - run: ./vendor/bin/pest --coverage --min=80


Pre-commit Hook (Husky — Node stacks)



// package.json


{


  "lint-staged": {


    "src/**/*.service.ts": ["jest --findRelatedTests --passWithNoTests"],


    "src/**/*.tsx": ["vitest related --run"]


  }


}



Part 9 — Quick Start Checklist

New Project



□ Install test library (one per stack — see Part 1)


□ Configure jest.config.ts / vitest.config.ts / pytest.ini / pest.php


□ Create .cursor/rules/ directory with all rule files from Part 3


□ Create CLAUDE.md at project root from Part 4


□ Add coverage thresholds to config


□ Add pre-commit hooks (Husky for Node, pre-commit for Python)


□ Add CI workflow from Part 8


□ Create test factory files (one per major entity)


□ Write first failing test → implement → green → commit


Existing Project



□ Add test library without touching existing code


□ Add .cursor/rules/ + CLAUDE.md


□ Run coverage on existing code → document current baseline


□ Pick 3 critical services → generate tests → set as new baseline


□ Add CI with threshold = current baseline (not ideal — current)


□ Raise threshold by 5% per sprint



Appendix — Install Commands Per Stack

NestJS



npm install --save-dev jest ts-jest @types/jest @nestjs/testing jest-mock-extended @golevelup/ts-jest


npx ts-jest config:init


React (Vite)



npm install --save-dev vitest @vitest/coverage-v8 @testing-library/react @testing-library/user-event @testing-library/jest-dom jsdom


Python



pip install pytest pytest-cov pytest-mock pytest-asyncio factory-boy


Angular



ng add @angular-builders/jest


npm install --save-dev jest jest-preset-angular @types/jest


Laravel



composer require pestphp/pest pestphp/pest-plugin-laravel --dev


./vendor/bin/pest --init



Last updated: 2025 — verify library major versions before adopting