Skip to content

Backend (Unit) Testing

Testing backend logic ensures that your API endpoints return the correct data and handle errors properly. With Hono and Bun Test, we can write fast and effective tests.

Bun comes with a built-in test runner. You can run tests using the bun test command. It looks for files ending in .test.ts, .spec.ts, etc.

Hono makes it easy to test endpoints by allowing you to simulate requests directly against the app instance using app.request().

Suppose you have a simple “Hello World” endpoint:

app.ts
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Bun!"));
export default app;

You can test it like this:

app.test.ts
import { describe, expect, test } from "bun:test";
import app from "./app";
describe("Basic Routes", () => {
test("GET / returns Hello Bun", async () => {
const res = await app.request("/");
expect(res.status).toBe(200);
expect(await res.text()).toBe("Hello Bun!");
});
});

Often, your handlers will interact with a database or external services. In unit tests, you want to isolate the handler logic. You can do this by mocking the dependencies.

If you are using dependency injection or passing services via context, you can pass mock implementations during the test.

Middleware is a crucial part of Hono apps. To test code that relies on external services (like a database), we can use mocks.

Here is an example of how to test a route while mocking a database function:

import { describe, expect, test, mock } from "bun:test";
import { Hono } from "hono";
describe("User Route with Mocks", () => {
test("GET /user/:id returns user data", async () => {
const app = new Hono();
// 1. Create a mock function to simulate a database call
const mockDb = mock(async (id) => ({ id, name: "Mocked User" }));
// 2. Define a route that uses the mock
app.get("/user/:id", async (c) => {
const id = c.req.param("id");
const user = await mockDb(id); // Call the mock instead of real DB
return c.json(user);
});
// 3. Make a request to the app
const res = await app.request("/user/123");
const data = await res.json();
// 4. Assertions
expect(res.status).toBe(200);
expect(data).toEqual({ id: "123", name: "Mocked User" });
expect(mockDb).toHaveBeenCalledWith("123");
});
});

In the exercise, you will practice writing a test for an auth middleware scenario.