Skip to main content
Learn how to isolate tests and prevent data contamination between tests using database transactions.

What is Database Test Isolation?

Sonamu wraps each test in a transaction and automatically rolls back when the test ends. This ensures:
  • Data doesn’t mix between tests
  • Always same results regardless of test execution order
  • No separate cleanup needed to restore DB to initial state

Automatic Transaction Management

bootstrap() Function

Sonamu’s bootstrap() function automatically manages transactions:

What bootstrap() Does

Key points:
  1. beforeEach: Create transaction before each test starts
  2. afterEach: Rollback transaction after each test ends
  3. Always rollback regardless of test success/failure

Test Environment DB Configuration

sonamu.config.ts

Test DB is configured in sonamu.config.ts:
Important:
  • Test DB is completely separate from development/production DB
  • Set pool.max: 1 to use single connection (guarantees transaction isolation)

DB Class Test Mode

The DB class automatically switches to test mode when NODE_ENV=test:

Transaction Isolation Mechanism

createTestTransaction()

Called in beforeEach to start a new transaction:
How it works:
  1. Get Write DB instance
  2. Start new transaction
  3. Store in testTransaction property
  4. All subsequent queries execute through this transaction

clearTestTransaction()

Called in afterEach to rollback and clean up transaction:
How it works:
  1. Rollback current transaction (cancel all changes)
  2. Initialize testTransaction to null
  3. Ready for next test

Practical Examples

Basic CRUD Test

Multiple Table Operations

Error Handling in Transactions

Complex Business Logic Test

Test Isolation Verification

Isolation Check Test

Manual Transaction Control

You can manually control transactions when needed:

Operations Outside Transaction (Caution)

Some operations execute outside transaction scope, so caution is needed:
Operations not rolled back by transactions:
  1. File system operations
  2. External API calls
  3. DDL statements (exception for PostgreSQL)
  4. Time functions (NOW(), CURRENT_TIMESTAMP, etc.)

File System Mocking

Use Naite Mock for file operations:
See API Mocking for details.

Performance Optimization

Single Connection Pool

In test environment, set pool.max: 1 to use only single connection:
Reason:
  • Same connection must be used to guarantee transaction isolation
  • Transactions aren’t shared with multiple connections

Limit Parallel Execution

Running tests sequentially is safer:
Or vitest.config.ts:

Cautions

Cautions for database testing:
  1. bootstrap() required: If bootstrap(vi) is not called, transactions are not created and data is actually saved to DB.
  2. Separate test DB: Always separate development DB and test DB. Development data could be accidentally deleted.
  3. Clean up external resources: Files, external API calls, etc. must be cleaned up manually.
  4. DDL caution: In MySQL, DDL statements commit immediately and are not rolled back. Avoid table creation/deletion in tests.
  5. Limit parallel execution: Sequential test execution is recommended for transaction isolation.

Next Steps

runWithMockContext

Testing with Mock Context

API Mocking

Mocking external API calls

Naite Logging

Recording and tracking test logs

Bootstrap

Test environment initialization