Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Тесты с app.request()

Тест — код, который сам отправляет запрос в приложение и проверяет ответ. В Hono для этого не нужен ни сервер, ни порт: метод app.request() передаёт запрос прямо в приложение и возвращает Response. Тесты запускает Vitest — популярная программа для тестов на TypeScript.

Приложение отдельно от сервера

Если тест импортирует src/index.ts, вместе с ним запустится сервер. Поэтому приложение выносят в отдельный файл. Создайте src/app.ts и перенесите туда всё, кроме serve():

// src/app.ts
import { Hono } from 'hono'
import posts from './routes/posts.js'
import auth from './routes/auth.js'
 
const app = new Hono()
 
app.route('/posts', posts)
app.route('/auth', auth)
 
export default app

В src/index.ts остаётся только запуск:

// src/index.ts
import { serve } from '@hono/node-server'
import app from './app.js'
 
serve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) })

Сервер работает как раньше, а src/app.ts можно импортировать в тестах.

Установка Vitest

npm install -D vitest

Создайте в корне проекта vitest.config.ts с переменными окружения для тестов:

// vitest.config.ts
import { defineConfig } from 'vitest/config'
 
export default defineConfig({
  test: {
    env: {
      DB_FILE: ':memory:',
      JWT_SECRET: 'test-secret',
    },
  },
})

Значение :memory: создаёт базу SQLite в памяти: она пустая при каждом запуске тестов и не трогает blog.db.

Первый тест

Создайте src/app.test.ts:

// src/app.test.ts
import { describe, expect, it } from 'vitest'
import app from './app.js'
 
describe('статьи', () => {
  it('отдаёт список', async () => {
    const res = await app.request('/posts')
    expect(res.status).toBe(200)
    expect(await res.json()).toEqual([])
  })
 
  it('возвращает 404 для несуществующей статьи', async () => {
    const res = await app.request('/posts/999')
    expect(res.status).toBe(404)
  })
})

Запустите тесты:

npx vitest

В терминале появятся два зелёных пункта и итог 2 passed. Vitest продолжит следить за файлами и перезапустит тесты при изменениях.

Запрос с телом и заголовками

Второй аргумент app.request() — те же настройки, что у fetch():

// src/app.test.ts
it('не создаёт статью без токена', async () => {
  const res = await app.request('/posts', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ title: 'Тест', body: 'Текст' }),
  })
  expect(res.status).toBe(401)
})

Тест проверяет, что middleware requireAuth не пропускает запрос без токена.

Скрипт test

Добавьте в package.json строку "test": "vitest run" в раздел scripts. Команда npm test прогонит тесты один раз и завершится — так их запускают перед развёртыванием.

Частая ошибка

Тесты работают с той же базой blog.db, что и сервер разработки. Тест создаёт статьи, удаляет их, и через день проверка «список пуст» перестаёт проходить, а ваши данные портятся. Для тестов всегда задавайте отдельную базу, как :memory: в vitest.config.ts.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.