Skip to main content
Database assertions are an experimental feature. The syntax and behavior may change in future releases.
Database assertions let you verify that an HTTP request produced the expected side effects in your database. After sending a request, hitspec runs a SQL query and asserts on the results.

Security

Database assertion blocks execute SQL queries against your database. You must pass the --allow-db flag to enable them. Without this flag, >>>db blocks are skipped.
hitspec run tests/ --allow-db

Basic Usage

Use the @db annotation to specify a database connection and a >>>db block for queries and assertions:
### Create a user and verify in database
# @name createUser
# @db sqlite://./test.db

POST {{baseUrl}}/api/users
Content-Type: application/json

{
  "name": "Jane Doe",
  "email": "jane@example.com"
}

>>>
expect status 201
<<<

>>>db
query SELECT COUNT(*) as count FROM users WHERE email = 'jane@example.com'
expect count == 1
<<<

Connection Strings

Specify the database connection using the @db annotation:
DatabaseConnection String
SQLitesqlite://./test.db or sqlite:./test.db
PostgreSQLpostgres://user:pass@localhost:5432/dbname
MySQLmysql://user:pass@localhost:3306/dbname
### PostgreSQL example
# @db postgres://testuser:testpass@localhost:5432/testdb

### MySQL example
# @db mysql://root:password@localhost:3306/myapp

### SQLite example
# @db sqlite://./test.db

Query and Assert Syntax

Inside a >>>db block, use query to run SQL and expect to assert on the result columns:
>>>db
query SELECT name, email, active FROM users WHERE id = 1
expect name == "Jane Doe"
expect email == "jane@example.com"
expect active == true
<<<

Supported Operators

OperatorExampleDescription
==expect count == 5Equals
!=expect status != "deleted"Not equals
>expect count > 0Greater than
>=expect count >= 1Greater than or equal
<expect age < 100Less than
<=expect score <= 10Less than or equal
containsexpect name contains "Jane"Contains substring
existsexpect email existsValue is not null
!existsexpect deleted_at !existsValue is null

Examples

Verify Record Creation

### Create order
# @name createOrder
# @db postgres://{{dbUser}}:{{dbPass}}@localhost:5432/{{dbName}}

POST {{baseUrl}}/api/orders
Content-Type: application/json

{
  "product_id": 42,
  "quantity": 3
}

>>>
expect status 201
expect body.id exists
<<<

>>>capture
orderId from body.id
<<<

>>>db
query SELECT product_id, quantity, status FROM orders WHERE id = {{createOrder.orderId}}
expect product_id == 42
expect quantity == 3
expect status == "pending"
<<<

Verify Record Deletion

### Delete user
# @name deleteUser
# @depends createUser
# @db sqlite://./test.db

DELETE {{baseUrl}}/api/users/{{createUser.userId}}

>>>
expect status 204
<<<

>>>db
query SELECT COUNT(*) as count FROM users WHERE id = {{createUser.userId}}
expect count == 0
<<<

Verify Aggregates

### Bulk import
# @name bulkImport
# @db postgres://{{dbUser}}:{{dbPass}}@localhost:5432/{{dbName}}

POST {{baseUrl}}/api/import
Content-Type: application/json

{
  "file": "data.csv"
}

>>>
expect status 200
<<<

>>>db
query SELECT COUNT(*) as total FROM imports WHERE batch_id IS NOT NULL
expect total > 0
<<<
Variable interpolation works inside >>>db blocks. You can use captured values, environment variables, and built-in functions in your SQL queries.
For CI/CD, use environment variables for database credentials and pass the --allow-db flag explicitly in your pipeline configuration.