Mengimplementasikan testing di Hono: unit testing routes dengan app.request(), integration testing dengan database in-memory, E2E testing dengan wrangler dev, dan code coverage dengan Bun test atau Vitest.

Setelah di episode 16 kita memahami performance optimization, pada episode ini kita akan memahami testing — lapisan jaminan kualitas yang memastikan kode berfungsi sebagaimana mestinya.
Hono menyediakan method app.request() yang memungkinkan test tanpa menjalankan server:
import { describe, it, expect } from 'bun:test'
import { Hono } from 'hono'
const app = new Hono()
.get('/', (c) => c.text('Hello Hono!'))
.get('/user/:id', (c) => c.json({ id: c.req.param('id') }))
describe('Routes', () => {
it('should return hello message', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hello Hono!')
})
it('should return user by id', async () => {
const res = await app.request('/user/123')
expect(res.status).toBe(200)
const data = await res.json()
expect(data.id).toBe('123')
})
})it('should create user', async () => {
const res = await app.request('/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John', email: 'john@example.com' }),
})
expect(res.status).toBe(201)
const data = await res.json()
expect(data.name).toBe('John')
})it('should return 400 for invalid body', async () => {
const res = await app.request('/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '' }),
})
expect(res.status).toBe(400)
})import { Database } from 'bun:sqlite'
import { drizzle } from 'drizzle-orm/bun-sqlite'
function createTestDb() {
const sqlite = new Database(':memory:')
return drizzle(sqlite)
}wrangler d1 create test-db
wrangler d1 execute test-db --local --file=schema.sqldescribe('E2E Auth Flow', () => {
const baseUrl = 'http://localhost:8787'
it('should login and access protected route', async () => {
const loginRes = await fetch(`${baseUrl}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'test@example.com', password: 'pass' }),
})
const { token } = await loginRes.json()
const profileRes = await fetch(`${baseUrl}/profile`, {
headers: { Authorization: `Bearer ${token}` },
})
expect(profileRes.status).toBe(200)
})
})bun test --coveragenpx vitest --coverageTip
Mulai dengan unit testing untuk route handler, lalu tambahkan integration testing untuk alur yang melibatkan database, dan E2E testing untuk flow kritis seperti autentikasi.
Pada episode 17 ini, kalian telah memahami testing di Hono — dari unit test hingga E2E dan coverage.
Inti yang harus dibawa pulang:
app.request() memungkinkan unit test tanpa running server.wrangler dev untuk E2E testing dalam simulated Workers environment.Di episode 18 selanjutnya kita akan memahami project structure dan scalability — struktur folder, modularisasi, scaling ke microservices, dan graceful shutdown. Sampai jumpa di episode 18!