mcpField
J
jest-testing

jest-testing

github.com/pluginagentmarketplace测试与质量2120 次安装43 周前更新
代码仓库

关于 jest-testing

jest-testing 是帮助开发者使用 Jest 测试 Node.js 应用的技能,涵盖测试编写、模拟、API 测试和覆盖率。它从基础测试结构延伸到集成测试与 CI/CD。

主要功能

  1. 01编写单元测试与异步测试
  2. 02模拟模块和函数
  3. 03使用 Supertest 测试 API
  4. 04生成代码覆盖率报告
  5. 05配置测试生命周期钩子

适用场景

  1. 01为 Node.js 函数编写测试
  2. 02验证 API 端点行为
  3. 03模拟外部依赖以隔离测试
  4. 04在 CI/CD 流程中运行测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pluginagentmarketplace/custom-plugin-nodejs --skill jest-testing

安装后在 Claude Code 中输入/jest-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
config.yaml
references/
GUIDE.md
scripts/
helper.py

详细介绍

Jest 测试技能

掌握使用 Jest 测试 Node.js 应用——这款令人愉悦的 JavaScript 测试框架。

快速开始

只需 3 步即可开始测试:

  1. 安装 - npm install --save-dev jest supertest
  2. 编写测试 - 创建 *.test.js 文件
  3. 运行 - npm test

核心概念

基本测试结构
// sum.test.js
const sum = require('./sum');

describe('sum function', () => {
  test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
  });

  test('adds negative numbers', () => {
    expect(sum(-1, -2)).toBe(-3);
  });
});
Jest 配置
// package.json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  },
  "jest": {
    "testEnvironment": "node",
    "coverageThreshold": {
      "global": {
        "branches": 80,
        "functions": 80,
        "lines": 80
      }
    }
  }
}
单元测试
// userService.test.js
const UserService = require('./userService');
const User = require('./models/User');

jest.mock('./models/User');

describe('UserService', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('createUser', () => {
    it('should create user successfully', async () => {
      const userData = {
        name: 'John',
        email: '[email protected]'
      };

      User.create.mockResolvedValue({ id: 1, ...userData });

      const result = await UserService.createUser(userData);

      expect(User.create).toHaveBeenCalledWith(userData);
      expect(result.id).toBe(1);
    });

    it('should throw error for duplicate email', async () => {
      User.create.mockRejectedValue(new Error('Email exists'));

      await expect(UserService.createUser({}))
        .rejects
        .toThrow('Email exists');
    });
  });
});

学习路径

初学者(1-2 周)
  • ✅ 配置 Jest 并编写基础测试
  • ✅ 理解测试结构(describe/it/expect)
  • ✅ 学习匹配器(toBe、toEqual 等)
  • ✅ 测试同步函数
中级(3-4 周)
  • ✅ 测试异步函数
  • ✅ 模拟模块和函数
  • ✅ 使用 Supertest 进行 API 测试
  • ✅ 生成代码覆盖率报告
高级(5-6 周)
  • ✅ 集成测试
  • ✅ 测试数据库操作
  • ✅ CI/CD 集成
  • ✅ 性能测试

使用 Supertest 进行 API 测试

const request = require('supertest');
const app = require('./app');

describe('User API', () => {
  describe('POST /api/users', () => {
    it('should create new user', async () => {
      const userData = {
        name: 'John',
        email: '[email protected]',
        password: 'password123'
      };

      const response = await request(app)
        .post('/api/users')
        .send(userData)
        .expect('Content-Type', /json/)
        .expect(201);

      expect(response.body).toHaveProperty('id');
      expect(response.body.email).toBe(userData.email);
    });

    it('should return 400 for invalid email', async () => {
      const response = await request(app)
        .post('/api/users')
        .send({ email: 'invalid' })
        .expect(400);

      expect(response.body).toHaveProperty('error');
    });
  });

  describe('GET /api/users/:id', () => {
    it('should return user by id', async () => {
      const response = await request(app)
        .get('/api/users/123')
        .expect(200);

      expect(response.body.id).toBe('123');
    });

    it('should return 404 for non-existent user', async () => {
      await request(app)
        .get('/api/users/999')
        .expect(404);
    });
  });
});

模拟模式

// Mock entire module
jest.mock('axios');
const axios = require('axios');

test('fetches data from API', async () => {
  axios.get.mockResolvedValue({ data: { id: 1 } });

  const result = await fetchUser(1);

  expect(axios.get).toHaveBeenCalledWith('/api/users/1');
  expect(result.id).toBe(1);
});

// Spy on function
test('calls callback', () => {
  const callback = jest.fn();

  processData('test', callback);

  expect(callback).toHaveBeenCalledWith('test');
  expect(callback).toHaveBeenCalledTimes(1);
});

// Mock timers
jest.useFakeTimers();

test('delays execution', () => {
  const callback = jest.fn();

  setTimeout(callback, 1000);
  jest.advanceTimersByTime(1000);

  expect(callback).toHaveBeenCalled();
});

测试生命周期钩子

describe('User Tests', () => {
  beforeAll(async () => {
    // Setup test database
    await connectTestDB();
  });

  afterAll(async () => {
    // Cleanup
    await disconnectTestDB();
  });

  beforeEach(async () => {
    // Clear data before each test
    await User.deleteMany({});
  });

  afterEach(() => {
    // Cleanup after each test
    jest.clearAllMocks();
  });

  test('...', () => {});
});

Jest 匹配器

// Equality
expect(value).toBe(expected)        // Strict equality (===)
expect(value).toEqual(expected)     // Deep equality
expect(value).not.toBe(expected)    // Negation

// Truthiness
expect(value).toBeDefined()
expect(value).toBeNull()
expect(value).toBeTruthy()
expect(value).toBeFalsy()

// Numbers
expect(value).toBeGreaterThan(3)
expect(value).toBeGreaterThanOrEqual(3)
expect(value).toBeLessThan(5)
expect(value).toBeCloseTo(0.3)      // Floating point

// Strings
expect(string).toMatch(/pattern/)
expect(string).toContain('substring')

// Arrays
expect(array).toContain(item)
expect(array).toHaveLength(3)

// Objects
expect(obj).toHaveProperty('key')
expect(obj).toMatchObject({ key: 'value' })

// Exceptions
expect(() => fn()).toThrow()
expect(() => fn()).toThrow('error message')

// Async
await expect(promise).resolves.toBe(value)
await expect(promise).rejects.toThrow()

代码覆盖率

# Run with coverage
npm test -- --coverage

# Coverage report shows:
# - Statements: % of code executed
# - Branches: % of if/else paths
# - Functions: % of functions called
# - Lines: % of lines executed

测试最佳实践

  • ✅ AAA 模式:准备、执行、断言
  • ✅ 每项测试只进行一次断言(理想情况下)
  • ✅ 使用描述性测试名称
  • ✅ 测试边界情况
  • ✅ 模拟外部依赖
  • ✅ 在测试后进行清理
  • ✅ 避免测试之间相互依赖
  • ✅ 以 80% 以上的覆盖率为目标

CI/CD 集成

# .github/workflows/test.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v3

适用场景

以下情况适合使用 Jest 测试:

  • 构建 Node.js 应用
  • 需要全面的测试覆盖率
  • 希望快速并行执行测试
  • 需要模拟和快照测试
  • 实施 CI/CD 流水线

相关技能

  • Express REST API(测试 API 端点)
  • 异步编程(测试异步代码)
  • 数据库集成(测试数据库操作)
  • JWT 身份验证(测试身份验证流程)

资源

评论

支持 Markdown