Unit tests

Extract pure domain logic

Move validation and transformation rules into small functions whose outputs depend only on explicit inputs.

Pure logic is cheap to test because it does not need a server, database, clock, network, or cleanup.

Extract book normalization and validation from the route handler. Return a value or a typed result instead of mutating global state. Keep HTTP status selection in the HTTP layer.

export function normalizeBook(input) {
  const title = input.title?.trim() ?? ''
  const author = input.author?.trim() ?? ''
  const year = input.year === '' || input.year == null
    ? null
    : Number(input.year)

  if (!title) return { ok: false, field: 'title', reason: 'required' }
  if (!author) return { ok: false, field: 'author', reason: 'required' }
  if (year !== null && !Number.isInteger(year)) {
    return { ok: false, field: 'year', reason: 'integer' }
  }

  return { ok: true, value: { title, author, year } }
}

This function owns a domain decision: what counts as a valid book value. The HTTP handler owns a transport decision: turning a failed result into a 400 JSON response. Keeping those decisions separate prevents a unit test from needing to construct a Request, and prevents the domain function from knowing about Hono.

Purity is not a goal by itself. Do not extract a one-line wrapper merely to mock it. Extract logic when explicit inputs and outputs make an important rule easier to see. The remaining route still needs an integration test, because a perfectly tested normalizer does not prove that the handler calls it or serializes its result correctly.

Create and test a function that trims title and author, validates length, and normalizes an optional year. Include one test that proves the input object is not mutated and one HTTP test that proves a validation failure becomes the documented response.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →