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.
Setting up Bun Test
Section titled “Setting up Bun Test”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.
Testing Hono Handlers
Section titled “Testing Hono Handlers”Hono makes it easy to test endpoints by allowing you to simulate requests directly against the app instance using app.request().
Example: Testing a Simple Endpoint
Section titled “Example: Testing a Simple Endpoint”Suppose you have a simple “Hello World” endpoint:
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Bun!"));
export default app;You can test it like this:
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!"); });});Mocking Dependencies
Section titled “Mocking Dependencies”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.
Testing Middleware & Mocks
Section titled “Testing Middleware & Mocks”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.