Spinning up a fresh database for every test makes a suite take twenty minutes. There is a faster way that still catches data leaks.
The worst bug a multi-tenant SaaS can ship is one customer seeing another customer's data. It is also the bug that unit tests almost never catch, because most test setups only create one account.
Two tenants in every fixture
I create two tenants in a shared setup, put one record in each, then run the test as the first tenant and assert the second tenant's record never appears. Every listing, every search, every export and every API endpoint gets one of these isolation tests.
It reads like overkill until the first time it fails. On a recruitment platform for a London agency, an isolation test caught a search endpoint that ignored the tenant scope when a filter was applied. That would have exposed candidate CVs across 60 agencies.
Keep it fast with transactions
Wrapping each test in a database transaction and rolling it back is far faster than migrating a fresh database. The suite on that recruitment platform has 840 tests and runs in 1 minute 50 seconds on GitHub Actions, which means developers actually run it before pushing.
Test the scope, not just the feature
I also add one architecture test that loads every model in the app and fails if a model with a tenant_id column does not use the tenant scope trait. New developers join, new models get added, and that one test is the guard that never gets tired.
Isolation tests have caught real leaks four times in client code before release. That is four emails to customers I never had to help a founder write.
Comments