Start learning free

LESSON 143 OF 173 · BACKEND: TESTS AND RUNNING IT

A Health Check

Practice

A shop on a server can stop working while you sleep. A monitoring service notices it for you: every minute it asks the shop a simple question over HTTP, and alerts you when the answer is wrong or doesn't come. The question is a health check, a route made only for this. A good one really asks the parts the shop needs, like its database, and says which one is down.

Asking can fail. Go has no exceptions: a function that can fail also returns an error value, which is nil when all went well. db.Exec runs a query and returns a result and an error; when the database can't answer, the error is not nil. You check it with if err != nil, answer, and return so the handler stops there. For example, in a route that reads a quantity:

quantity, err := strconv.Atoi(r.URL.Query().Get("quantity"))
if err != nil {
    writeJSON(w, 400, map[string]string{"error": "quantity must be a number"})
    return
}

The cheapest question for a database is SELECT 1: it reads no table and just answers 1. While the database is down, the health check still answers 200 with status ok, because the shop itself answers; its database part tells you where to look.

The check plays the monitor, stops the database for a minute, then lets it answer again:

GET /health  →  200  {"database": "ok", "status": "ok"}
GET /products/count  →  200  {"count": 8}
(the database stops answering)
GET /health  →  200  {"database": "down", "status": "ok"}
GET /products/count  →  500  Internal Server Error
(the database answers again)
GET /health  →  200  {"database": "ok", "status": "ok"}

Your task: add GET /health, which runs SELECT 1 with db.Exec and answers {"status": "ok", "database": "ok"}, or "down" for the database when the query returns an error. Then write TestHealth, which checks the status code and the whole JSON body. The check runs it on the shop, where it must pass, and on a copy whose health query has a typo, so it always says down, where it must fail.


Assignment
Follow the Coding Tutorial to build the /health route and a test that checks its whole answer.


Hint
Skip the query's result with _ and keep only err. Don't forget the return inside the if: without it the handler goes on and writes the ok answer too. A test that checks only the 200 lets the typo copy through: decode the body into a map and compare it too.


STEP 1 OF 11
    Ctrl + Enter to check