Skip to content

测试助手

¥Testing Helper

Testing Helper 提供使 Hono 应用测试更容易的功能。

¥The Testing Helper provides functions to make testing of Hono applications easier.

导入

¥Import

ts
import { Hono } from 'hono'
import { testClient } from 'hono/testing'

testClient()

testClient() 函数将 Hono 的实例作为其第一个参数,并返回一个根据你的 Hono 应用的路由类型确定的对象,类似于 Hono 客户端。这允许你以类型安全的方式调用你定义的路由,并在测试中使用编辑器自动补齐功能。

¥The testClient() function takes an instance of Hono as its first argument and returns an object typed according to your Hono application's routes, similar to the Hono Client. This allows you to call your defined routes in a type-safe manner with editor autocompletion within your tests.

关于类型推断的重要说明:

¥Important Note on Type Inference:

为了让 testClient 正确推断路由类型并提供自动补全功能,你必须直接在 Hono 实例上使用链式方法定义路由。

¥For the testClient to correctly infer the types of your routes and provide autocompletion, you must define your routes using chained methods directly on the Hono instance.

类型推断依赖于流经 .get().post() 等链式调用的类型。如果你在创建 Hono 实例后单独定义路由(如 "Hello World" 示例中所示的常见模式:const app = new Hono(); app.get(...)),testClient 将不具备特定路由所需的类型信息,你将无法获得类型安全的客户端功能。

¥The type inference relies on the type flowing through the chained .get(), .post(), etc., calls. If you define routes separately after creating the Hono instance (like the common pattern shown in the "Hello World" example: const app = new Hono(); app.get(...)), the testClient will not have the necessary type information for specific routes, and you won't get the type-safe client features.

示例:

¥Example:

此示例有效,因为 .get() 方法直接链接到 new Hono() 调用:

¥This example works because the .get() method is chained directly onto the new Hono() call:

ts
// index.ts
const app = new Hono().get('/search', (c) => {
  const query = c.req.query('q')
  return c.json({ query: query, results: ['result1', 'result2'] })
})

export default app
ts
// index.test.ts
import { Hono } from 'hono'
import { testClient } from 'hono/testing'
import { describe, it, expect } from 'vitest' // Or your preferred test runner
import app from './app'

describe('Search Endpoint', () => {
  // Create the test client from the app instance
  const client = testClient(app)

  it('should return search results', async () => {
    // Call the endpoint using the typed client
    // Notice the type safety for query parameters (if defined in the route)
    // and the direct access via .$get()
    const res = await client.search.$get({
      query: { q: 'hono' },
    })

    // Assertions
    expect(res.status).toBe(200)
    expect(await res.json()).toEqual({
      query: 'hono',
      results: ['result1', 'result2'],
    })
  })
})

要在测试中包含标头,请将其作为调用中的第二个参数传递。第二个参数也可以将 init 属性作为 RequestInit 对象,从而允许你设置标头、方法、正文等。了解更多关于 init 属性 此处 的信息。

¥To include headers in your test, pass them as the second parameter in the call. The second parameter can also take an init property as a RequestInit object, allowing you to set headers, method, body, etc. Learn more about the init property here.

ts
// index.test.ts
import { Hono } from 'hono'
import { testClient } from 'hono/testing'
import { describe, it, expect } from 'vitest' // Or your preferred test runner
import app from './app'

describe('Search Endpoint', () => {
  // Create the test client from the app instance
  const client = testClient(app)

  it('should return search results', async () => {
    // Include the token in the headers and set the content type
    const token = 'this-is-a-very-clean-token'
    const res = await client.search.$get(
      {
        query: { q: 'hono' },
      },
      {
        headers: {
          Authorization: `Bearer ${token}`,
          'Content-Type': `application/json`,
        },
      }
    )

    // Assertions
    expect(res.status).toBe(200)
    expect(await res.json()).toEqual({
      query: 'hono',
      results: ['result1', 'result2'],
    })
  })
})

Hono v4.8 中文网 - 粤ICP备13048890号