/integration-testing
集成测试方法论,验证模块间协作、数据库交互、服务间调用,参考 Testcontainers、Testing Library、WireMock 等开源实践
Claude Code
$ npx -y skills add echoVic/boss-skill --skill integration-testing --agent claude-code
Codex
$ npx skills add echoVic/boss-skill --skill integration-testing -a codex -y
Cursor
$ npx skills add echoVic/boss-skill --skill integration-testing -a cursor -y
Gemini CLI
$ npx skills add echoVic/boss-skill --skill integration-testing -a gemini-cli -y
GitHub Copilot
$ npx skills add echoVic/boss-skill --skill integration-testing -a github-copilot -y
OpenCode
$ npx skills add echoVic/boss-skill --skill integration-testing -a opencode -y
Windsurf
$ npx skills add echoVic/boss-skill --skill integration-testing -a windsurf -y
SKILL.md
integration-testing.SKILL.mdname: qa/integration-testing
description: 集成测试方法论,验证模块间协作、数据库交互、服务间调用,参考 Testcontainers、Testing Library、WireMock 等开源实践
version: 1.0.0
agent: qa
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
- shared/tech-stack-detection
triggers:
- 需要验证模块间协作时
- 需要测试数据库真实交互时
- 需要测试服务间调用时
- 需要验证前端组件与 API 集成时
metadata:
internal: true
集成测试方法论
> 参考开源实践:Testcontainers、Testing Library、WireMock、Testcontainers-go、Django Test Client
集成测试 vs 单元测试
| 维度 | 单元测试 | 集成测试 | | ---- | -------------- | -------------------- | | 范围 | 单个函数/组件 | 多个模块协作 | | 依赖 | Mock 外部依赖 | 真实依赖(DB、HTTP) | | 速度 | 快(ms) | 较慢(s) | | 目的 | 验证逻辑正确性 | 验证模块间协作 | | 数据 | Mock 数据 | 测试数据库/真实数据 |
1. 后端集成测试
1.1 数据库集成测试
使用真实数据库(Testcontainers 或测试数据库),不 mock Repository 层。
Node.js + Testcontainers (PostgreSQL)
// tests/integration/userRepository.test.ts
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { PrismaClient } from '@prisma/client';
import { UserRepository } from '../../src/repositories/userRepository';
describe('UserRepository (integration)', () => {
let container: StartedPostgreSqlContainer;
let prisma: PrismaClient;
let repo: UserRepository;
beforeAll(async () => {
container = await new PostgreSqlContainer().start();
prisma = new PrismaClient({ datasources: { db: { url: container.getConnectionUri() } } });
await prisma.$executeRawUnsafe('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');
repo = new UserRepository(prisma);
}, 60000);
afterAll(async () => {
await prisma.$disconnect();
await container.stop();
}, 60000);
beforeEach(async () => {
await prisma.user.deleteMany();
});
it('creates and retrieves user', async () => {
const user = await repo.create({ name: 'Alice', email: 'alice@example.com' });
const found = await repo.findByEmail('alice@example.com');
expect(found?.id).toBe(user.id);
expect(found?.name).toBe('Alice');
});
it('returns null for non-existent email', async () => {
const found = await repo.findByEmail('nonexistent@example.com');
expect(found).toBeNull();
});
});Python + pytest (PostgreSQL)
# tests/integration/test_user_repository.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.models import Base
from app.repositories import UserRepository
@pytest.fixture(scope="module")
def db_session():
engine = create_engine("postgresql://test:test@localhost:5432/test_db")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
yield session
session.close()
Base.metadata.drop_all(engine)
def test_create_and_get_user(db_session):
repo = UserRepository(db_session)
user = repo.create(name="Alice", email="alice@example.com")
found = repo.find_by_email("alice@example.com")
assert found.id == user.id
assert found.name == "Alice"1.2 API + DB 端到端集成
// tests/integration/user-api.test.ts
import request from 'supertest';
import { app } from '../../src/app';
import { prisma } from '../../src/db';
describe('User API + DB integration', () => {
beforeAll(async () => {
await prisma.$connect();
});
afterAll(async () => {
await prisma.$disconnect();
});
beforeEach(async () => {
await prisma.user.deleteMany();
});
it('POST creates user in database', async () => {
const res = await request(app)
.post('/api/users')
.send({ name: 'Alice', email: 'alice@example.com' })
.expect(201);
// 验证数据库中确实存在
const dbUser = await prisma.user.findUnique({ where: { id: res.body.data.id } });
expect(dbUser).not.toBeNull();
expect(dbUser?.name).toBe('Alice');
});
it('GET returns persisted user', async () => {
await prisma.user.create({ data: { name: 'Bob', email: 'bob@example.com' } });
const res = await request(app).get('/api/users').expect(200);
expect(res.body.data.items).toHaveLength(1);
expect(res.body.data.items[0].name).toBe('Bob');
});
it('DELETE removes user from database', async () => {
const user = await prisma.user.create({
data: { name: 'Charlie', email: 'charlie@example.com' },
});
await request(app).delete(`/api/users/${user.id}`).expect(200);
const dbUser = await prisma.user.findUnique({ where: { id: user.id } });
expect(dbUser).toBeNull();
});
});1.3 服务间调用集成
使用 WireMock 或 Mock Service Worker 模拟外部服务:
// tests/integration/order-service.test.ts
import { WireMock } from 'wiremock-captain';
describe('OrderService integration with PaymentService', () => {
let wiremock: WireMock;
beforeAll(async () => {
wiremock = new WireMock('http://localhost:8080');
});
it('marks order as paid when payment succeeds', async () => {
// Mock 支付服务成功响应
await wiremock.stubFor({
request: { method: 'POST', url: '/payments' },
response: { status: 200, jsonBody: { success: true, transactionId: 'tx-123' } },
});
const order = await orderService.create({ userId: '1', items: [] });
const paid = await orderService.pay(order.id, { method: 'credit_card' });
expect(paid.status).toBe('paid');
});
it('keeps order pending when payment fails', async () => {
await wiremock.stubFor({
request: { method: 'POST', url: '/payments' },
response: { status: 402, jsonBody: { error: 'INSUFFICIENT_FUNDS' } },
});
const order = await orderService.create({ userId: '1', items: [] });
await expect(orderService.pay(order.id, { method: 'credit_card' })).rejects.toThrow(
'Payment failed',
);
const refreshed = await orderService.getById(order.id);
expect(refreshed.status).toBe('pending');
});
});2. 前端集成测试
2.1 组件 + 状态管理 + API 集成
使用 Testing Library + MSW (Mock Service Worker):
// tests/integration/UserList.test.tsx
import { rRead more
name: qa/integration-testing description: 集成测试方法论,验证模块间协作、数据库交互、服务间调用,参考 Testcontainers、Testing Library、WireMock 等开源实践 version: 1.0.0 agent: qa type: methodology user-invocable: false agent-invocable: true dependencies: - shared/tech-stack-detection triggers: - 需要验证模块间协作时 - 需要测试数据库真实交互时 - 需要测试服务间调用时 - 需要验证前端组件与 API 集成时 metadata: internal: true
集成测试方法论
> 参考开源实践:Testcontainers、Testing Library、WireMock、Testcontainers-go、Django Test Client
集成测试 vs 单元测试
| 维度 | 单元测试 | 集成测试 | | ---- | -------------- | -------------------- | | 范围 | 单个函数/组件 | 多个模块协作 | | 依赖 | Mock 外部依赖 | 真实依赖(DB、HTTP) | | 速度 | 快(ms) | 较慢(s) | | 目的 | 验证逻辑正确性 | 验证模块间协作 | | 数据 | Mock 数据 | 测试数据库/真实数据 |
1. 后端集成测试
1.1 数据库集成测试
使用真实数据库(Testcontainers 或测试数据库),不 mock Repository 层。
Node.js + Testcontainers (PostgreSQL)
// tests/integration/userRepository.test.ts
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { PrismaClient } from '@prisma/client';
import { UserRepository } from '../../src/repositories/userRepository';
describe('UserRepository (integration)', () => {
let container: StartedPostgreSqlContainer;
let prisma: PrismaClient;
let repo: UserRepository;
beforeAll(async () => {
container = await new PostgreSqlContainer().start();
prisma = new PrismaClient({ datasources: { db: { url: container.getConnectionUri() } } });
await prisma.$executeRawUnsafe('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');
repo = new UserRepository(prisma);
}, 60000);
afterAll(async () => {
await prisma.$disconnect();
await container.stop();
}, 60000);
beforeEach(async () => {
await prisma.user.deleteMany();
});
it('creates and retrieves user', async () => {
const user = await repo.create({ name: 'Alice', email: 'alice@example.com' });
const found = await repo.findByEmail('alice@example.com');
expect(found?.id).toBe(user.id);
expect(found?.name).toBe('Alice');
});
it('returns null for non-existent email', async () => {
const found = await repo.findByEmail('nonexistent@example.com');
expect(found).toBeNull();
});
});Python + pytest (PostgreSQL)
# tests/integration/test_user_repository.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.models import Base
from app.repositories import UserRepository
@pytest.fixture(scope="module")
def db_session():
engine = create_engine("postgresql://test:test@localhost:5432/test_db")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
yield session
session.close()
Base.metadata.drop_all(engine)
def test_create_and_get_user(db_session):
repo = UserRepository(db_session)
user = repo.create(name="Alice", email="alice@example.com")
found = repo.find_by_email("alice@example.com")
assert found.id == user.id
assert found.name == "Alice"1.2 API + DB 端到端集成
// tests/integration/user-api.test.ts
import request from 'supertest';
import { app } from '../../src/app';
import { prisma } from '../../src/db';
describe('User API + DB integration', () => {
beforeAll(async () => {
await prisma.$connect();
});
afterAll(async () => {
await prisma.$disconnect();
});
beforeEach(async () => {
await prisma.user.deleteMany();
});
it('POST creates user in database', async () => {
const res = await request(app)
.post('/api/users')
.send({ name: 'Alice', email: 'alice@example.com' })
.expect(201);
// 验证数据库中确实存在
const dbUser = await prisma.user.findUnique({ where: { id: res.body.data.id } });
expect(dbUser).not.toBeNull();
expect(dbUser?.name).toBe('Alice');
});
it('GET returns persisted user', async () => {
await prisma.user.create({ data: { name: 'Bob', email: 'bob@example.com' } });
const res = await request(app).get('/api/users').expect(200);
expect(res.body.data.items).toHaveLength(1);
expect(res.body.data.items[0].name).toBe('Bob');
});
it('DELETE removes user from database', async () => {
const user = await prisma.user.create({
data: { name: 'Charlie', email: 'charlie@example.com' },
});
await request(app).delete(`/api/users/${user.id}`).expect(200);
const dbUser = await prisma.user.findUnique({ where: { id: user.id } });
expect(dbUser).toBeNull();
});
});1.3 服务间调用集成
使用 WireMock 或 Mock Service Worker 模拟外部服务:
// tests/integration/order-service.test.ts
import { WireMock } from 'wiremock-captain';
describe('OrderService integration with PaymentService', () => {
let wiremock: WireMock;
beforeAll(async () => {
wiremock = new WireMock('http://localhost:8080');
});
it('marks order as paid when payment succeeds', async () => {
// Mock 支付服务成功响应
await wiremock.stubFor({
request: { method: 'POST', url: '/payments' },
response: { status: 200, jsonBody: { success: true, transactionId: 'tx-123' } },
});
const order = await orderService.create({ userId: '1', items: [] });
const paid = await orderService.pay(order.id, { method: 'credit_card' });
expect(paid.status).toBe('paid');
});
it('keeps order pending when payment fails', async () => {
await wiremock.stubFor({
request: { method: 'POST', url: '/payments' },
response: { status: 402, jsonBody: { error: 'INSUFFICIENT_FUNDS' } },
});
const order = await orderService.create({ userId: '1', items: [] });
await expect(orderService.pay(order.id, { method: 'credit_card' })).rejects.toThrow(
'Payment failed',
);
const refreshed = await orderService.getById(order.id);
expect(refreshed.status).toBe('pending');
});
});2. 前端集成测试
2.1 组件 + 状态管理 + API 集成
使用 Testing Library + MSW (Mock Service Worker):
// tests/integration/UserList.test.tsx
import { rLanguages / 语言 / 言語 / 언어 / Idiomas / Langues: English · 中文 · 日本語 · 한국어 · Español · Français · Português This project is part of the AtomGit G-Star Incubation Program.
Other skills on boss.
brainstorming
你是 Boss 的前置环节。用户通常只会丢过来一句话——可能是"帮我做个 XX"或者"我想搞个 XX"。你的工作是把这句话**翻译成下游流水线能跑起来的需求**。
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
accessibility
Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…
compiler-commit
Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…
Questions about integration-testing.
- Which coding agents can use integration-testing?
- integration-testing installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

