1.內建測試運行器(節點:測試)
import { describe, it, before, after, mock } from 'node:test'
import assert from 'node:assert/strict'
describe('UserService', () => {
let db: Database
before(async () => {
db = await Database.connect(':memory:')
await db.migrate()
})
after(async () => {
await db.close()
})
it('creates a user', async () => {
const user = await createUser(db, { name: 'Test', email: '[email protected]' })
assert.strictEqual(user.name, 'Test')
assert.ok(user.id)
})
it('rejects duplicate email', async () => {
await assert.rejects(
() => createUser(db, { name: 'Test2', email: '[email protected]' }),
{ message: /unique constraint/i }
)
})
it('mocks external service', async () => {
const sendEmail = mock.fn(async () => ({ success: true }))
const result = await sendEmail('[email protected]', 'Hello')
assert.strictEqual(sendEmail.mock.calls.length, 1)
})
})
node --test --test-reporter spec src/**/*.test.ts
2.維泰斯特
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
coverage: {
provider: 'v8',
reporter: ['text', 'html', 'lcov'],
include: ['src/**'],
exclude: ['src/**/*.test.ts'],
},
},
})
// src/services/user.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest'
describe('UserService', () => {
const mockDb = {
query: vi.fn(),
}
beforeEach(() => {
vi.clearAllMocks()
})
it('finds user by id', async () => {
mockDb.query.mockResolvedValue({
rows: [{ id: '1', name: 'Test' }]
})
const user = await findUser(mockDb as any, '1')
expect(user).toEqual({ id: '1', name: 'Test' })
expect(mockDb.query).toHaveBeenCalledWith(
expect.stringContaining('SELECT'),
['1']
)
})
})
3.HTTP測試(超級測試)
import request from 'supertest'
import { createApp } from '../src/app'
const app = createApp()
describe('API', () => {
it('GET /api/users returns users', async () => {
const res = await request(app)
.get('/api/users')
.expect(200)
.expect('Content-Type', /json/)
expect(res.body).toBeInstanceOf(Array)
expect(res.body[0]).toHaveProperty('name')
})
it('POST /api/users creates user', async () => {
const res = await request(app)
.post('/api/users')
.send({ name: 'New User', email: '[email protected]' })
.expect(201)
expect(res.body.name).toBe('New User')
})
it('returns 401 without auth', async () => {
await request(app)
.get('/api/admin')
.expect(401)
})
})
4. HTTP 模擬(Nock)
import nock from 'nock'
it('handles external API', async () => {
nock('https://api.github.com')
.get('/users/octocat')
.reply(200, { login: 'octocat', id: 1 })
const user = await fetchGitHubUser('octocat')
expect(user.login).toBe('octocat')
})
5. 測試容器
import { PostgreSqlContainer } from '@testcontainers/postgresql'
let container: any
let connectionString: string
beforeAll(async () => {
container = await new PostgreSqlContainer().start()
connectionString = container.getConnectionUri()
await runMigrations(connectionString)
}, 30000)
afterAll(async () => {
await container.stop()
})
下一篇: 性能分析和優化 — V8 分析器、火焰圖、Clinic.js。