Test that a failed request writes no row
Send a bad request in a zriz pipeline, then query the database. Status 400 and zero rows prove that a refused request stores nothing.
The problem
An API can answer 400 and write a part of the data before it stops. The client sees an error, and the database has a row that nobody owns. Only a query after the request shows this.
The test
The example is a shop API with a MySQL database. The test signs up with no name, then looks for the e-mail in the table users.
Start from a project that zz init made: the quick start gives the commands. Add the action register, the database value, and the database resource.
.zriz/resources/target.json:
{
"type": "http",
"description": "Your app under test",
"base-url": "${env.TARGET_URL}",
"headers": { "Content-Type": "application/json" },
"actions": {
"check": { "method": "GET", "path": "/api/health" },
"register": { "method": "POST", "path": "/api/auth/register" }
}
}
.zriz/environments/local.json:
{
"values": {
"TARGET_URL": "http://localhost:9080",
"SHOP_DB": "user:pass@tcp(localhost:3306)/shop"
},
"sensitive": ["SHOP_DB"]
}
.zriz/resources/shopdb.json:
{
"type": "sql",
"connection": "${env.SHOP_DB}",
"read-only": true,
"actions": {
"users-by-email": { "query": "SELECT id FROM users WHERE email = ${ctx.email}" }
}
}
.zriz/pipelines/bad-request-no-row.json:
{
"description": "A refused sign-up writes no row",
"steps": [
{ "set": { "email": "u-${gen.uuid}@test.com" } },
{
"call": "target/register",
"body": { "email": "${ctx.email}", "password": "secret123" },
"expect": [["status", "==", 400]]
},
{
"call": "shopdb/users-by-email",
"expect": [["row-count", "==", 0]]
}
]
}
Run it
zz run bad-request-no-row
"status":"pass"
What it proves
status == 400: the API refuses the request.row-count == 0: the refused request stored nothing. A row here means that the API writes before it checks the input.${gen.uuid}in the e-mail: no older run made this row, so zero rows is a true result.
Common mistake: A test that reads only the status passes when the API writes half of the data. Query each table that the request can write.
Next
- Test a login flow from sign-up to token
- Test an API call and the database row gives each step for your own database.