Hi everyone,
I’ve been reading the “Designing Elixir Systems with OTP” book, and got to the chapter on unit testing the persistence layer of the application. The sample app uses Ecto and PostgreSql.
For full context, the unit test in question is here on Github: https://github.com/iarekk/designing-elixir-systems-otp/blob/main/mastery/test/mastery_test.exs
The book provides the following code for the unit test to ‘configure the test environment to use a sandbox environ- ment that rolls back new changes after every test’:
in config/test.exs
:
use Mix.Config
config :mastery_persistence, MasteryPersistence.Repo, database: "mastery_test",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
and in the unit test setup:
# called in the setup()
defp enable_persistence() do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)
end
After reading Ecto documentation, I ended up adding this line to the method above
Ecto.Adapters.SQL.Sandbox.mode(Repo, {:shared, self()})
to make the unit tests revert the changes in the DB, but I don’t seems to understand why it’s needed, or why ‘revert all unit test DB changes’ isn’t the default behaviour.
Commit adding that line here: commit
So mostly I’m confused on:
- why is the ‘sandbox’ mode not sandboxing/rolling back the changes by default, contrary to the documentation claims
- why the magical command of setting the mode to ‘shared’ enables the rollback
For example, here the documentation states in passing “Since the SQL Sandbox mode rolls back transactions, tests might report false positives because deferred constraints are never checked by the database…”
https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html#module-deferred-constraints