What is the difference between unit tests and integration tests for databases?
Answer
For code that interacts with databases, there are two approaches. Unit testing with mocks: replace the database with a mock/stub. The repository or query is tested in isolation. Pros: fast, no setup. Cons: doesn't test the actual SQL query, misses database-specific behavior (type coercions, constraint violations, query performance). Mocked tests can pass while the real database query is broken. Integration testing with a real database: use a real database (same type as production). Options: (1) In-memory databases (SQLite for EF Core, H2 for Java) — fast but may behave differently from production PostgreSQL/MySQL. (2) Testcontainers: spin up a real Docker container of PostgreSQL/MySQL per test run — identical to production, slower to start. (3) Shared test database: use a dedicated test schema/database — fast start, but requires careful cleanup. Best practice: use Testcontainers for integration tests. For unit tests of business logic, mock the repository interface. Test actual repository/query implementations in integration tests against a real database.