测试
测试至关重要。 实际上,测试 Hono 应用非常简单。不同运行时的测试环境构建方式各不相同,但基本步骤一致。本节以 Cloudflare Workers 与 Vitest 为例。
TIP
Cloudflare 推荐将 Vitest 与 @cloudflare/vitest-pool-workers 搭配使用。详情请参阅 Cloudflare Workers 文档中的 Vitest integration。
请求与响应
测试时只需创建一个 Request,并传给 Hono 应用来验证响应。你也可以使用便捷的 app.request 方法。
TIP
如需类型完备的测试客户端,可查看测试助手。
以下示例展示了一个简单的 REST API:
ts
app.get('/posts', (c) => {
return c.text('Many posts')
})
app.post('/posts', (c) => {
return c.json(
{
message: 'Created',
},
201,
{
'X-Custom': 'Thank you',
}
)
})发起 GET /posts 请求并断言响应:
ts
describe('Example', () => {
test('GET /posts', async () => {
const res = await app.request('/posts')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Many posts')
})
})若要测试 POST /posts,可以这样写:
ts
test('POST /posts', async () => {
const res = await app.request('/posts', {
method: 'POST',
})
expect(res.status).toBe(201)
expect(res.headers.get('X-Custom')).toBe('Thank you')
expect(await res.json()).toEqual({
message: 'Created',
})
})携带 JSON 数据发起 POST /posts 请求:
ts
test('POST /posts', async () => {
const res = await app.request('/posts', {
method: 'POST',
body: JSON.stringify({ message: 'hello hono' }),
headers: new Headers({ 'Content-Type': 'application/json' }),
})
expect(res.status).toBe(201)
expect(res.headers.get('X-Custom')).toBe('Thank you')
expect(await res.json()).toEqual({
message: 'Created',
})
})以 multipart/form-data 发起请求:
ts
test('POST /posts', async () => {
const formData = new FormData()
formData.append('message', 'hello')
const res = await app.request('/posts', {
method: 'POST',
body: formData,
})
expect(res.status).toBe(201)
expect(res.headers.get('X-Custom')).toBe('Thank you')
expect(await res.json()).toEqual({
message: 'Created',
})
})也可以传入原生 Request 实例:
ts
test('POST /posts', async () => {
const req = new Request('http://localhost/posts', {
method: 'POST',
})
const res = await app.request(req)
expect(res.status).toBe(201)
expect(res.headers.get('X-Custom')).toBe('Thank you')
expect(await res.json()).toEqual({
message: 'Created',
})
})通过上述方式,即可实现类似端到端(E2E)的测试。
Env
如果需要在测试中设置 c.env,可以将其作为第三个参数传给 app.request,适合模拟 Cloudflare Workers Bindings 等场景:
ts
const MOCK_ENV = {
API_HOST: 'example.com',
DB: {
prepare: () => {
/* mocked D1 */
},
},
}
test('GET /posts', async () => {
const res = await app.request('/posts', {}, MOCK_ENV)
})