Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Database Tests page #15

Merged
merged 5 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions content/docs/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@
"contentPath": "./testing/http_tests.md",
"category": "Testing"
},
{
"permalink": "database-tests",
"title": "Database tests",
"contentPath": "./testing/database_tests.md",
"category": "Testing"
},
{
"permalink": "browser-tests",
"title": "Browser tests",
Expand Down
98 changes: 98 additions & 0 deletions content/docs/testing/database_tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
summary: "Learn how to test code that interacts with your databases in AdonisJS: simple steps for setting up, resetting, and keeping databases clean during tests."
---

# Database tests

Database tests refer to testing how your application interacts with the database. This includes testing what is written to the database, how to run migrations before the tests, and how to keep the database clean between tests.

## Migrating the database

Before executing your tests that interact with the database, you would want to run your migrations first. We have two hooks available in the `testUtils` service for that, which you can configure inside the `tests/bootstrap.ts` file.

### Reset database after each run cycle

The first option we have is `testUtils.db().migrate()`. This hook will first run all your migrations, and then rollback everything.

```ts
// title: tests/bootstrap.ts
import testUtils from '@adonisjs/core/services/test_utils'

export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [
() => testUtils.db().migrate(),
],
teardown: [],
}
```

By configuring the hook here, what will happen is:

- Before running our tests, the migrations will be executed.
- At the end of our tests, the database will be rolled back.

So, each time we run our tests, we will have a fresh and empty database.

### Truncate tables after each run cycle

Resetting the database after each run cycle is a good option, but it can be slow if you have a lot of migrations. Another option is to truncate the tables after each run cycle. This option will be faster, as the migrations will only be executed once : the very first time you run your tests on a fresh database.


At the end of each run cycle, the tables will just be truncated, but our schema will be kept. So, the next time we run our tests, we will have an empty database, but the schema will already be in place, so there's no need to run every migration again.

```ts
// title: tests/bootstrap.ts
import testUtils from '@adonisjs/core/services/test_utils'

export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [
() => testUtils.db().truncate(),
],
}
```

## Seeding the database

If you need to seed your database, you can use the `testUtils.db().seed()` hook. This hook will run all your seeds before running your tests.

```ts
// title: tests/bootstrap.ts
import testUtils from '@adonisjs/core/services/test_utils'

export const runnerHooks: Required<Pick<Config, 'setup' | 'teardown'>> = {
setup: [
() => testUtils.db().seed(),
],
}
```

## Keeping the database clean between tests

### Global transaction

When running tests, you may want to keep your database clean between each test. For that, you can use the `testUtils.db().withGlobalTransaction()` hook. This hook will start a transaction before each test and roll it back at the end of the test.

```ts
// title: tests/unit/user.spec.ts
import { test } from '@japa/runner'
import testUtils from '@adonisjs/core/services/test_utils'

test.group('User', (group) => {
group.each.setup(() => testUtils.db().withGlobalTransaction())
})
```

Note that if you are using any transactions in your tested code, this will not work as transactions cannot be nested. In this case, you can use the `testUtils.db().migrate()` or `testUtils.db().truncate()` hook instead.

### Truncate tables

As mentioned above, the global transaction will not work if you are using transactions in your tested code. In this case, you can use the `testUtils.db().truncate()` hook. This hook will truncate all your tables after each test.

```ts
// title: tests/unit/user.spec.ts
import { test } from '@japa/runner'

test.group('User', (group) => {
group.each.setup(() => testUtils.db().truncate())
})
```