Test, build, and ship
Test an HTTP server
Start a Bun server on a temporary port, make a real HTTP request, and stop it reliably after the test.
10 minute lesson
An HTTP test should check the response a client receives. Bun can start a server on an available port by using port 0.
Move server creation into server.ts:
export function createServer(port = 0) {
return Bun.serve({
port,
routes: {
'/health': Response.json({ ok: true }),
},
fetch() {
return new Response('Not found', { status: 404 })
},
})
}
Use it from index.ts:
import { createServer } from './server'
const port = Number(Bun.env.PORT ?? 3000)
const server = createServer(port)
console.log(`Listening on ${server.url}`)
Now create server.test.ts:
import { expect, test } from 'bun:test'
import { createServer } from './server'
test('reports that the server is healthy', async () => {
const server = createServer()
try {
const url = new URL('/health', server.url)
const response = await fetch(url)
expect(response.status).toBe(200)
expect(await response.json()).toEqual({ ok: true })
} finally {
server.stop(true)
}
})
The test uses the real HTTP stack. It does not assume a fixed port, so it can run beside another development server.
The finally block matters. Bun stops the server even when an assertion fails. Without cleanup, the test process can keep listening or affect the next test.
Use this pattern for a few important request paths. Keep validation and database logic testable as smaller functions too, so every behavior does not require a network request.
Lesson completed