My use case is when using with Triplex, in every test i need a “tenant” to exist. The default setup where a tenant is created in every test is unacceptably slow (each test takes >1 second).
My solution is to make a new module called TenantCase
:
defmodule MyApp.TenantCase do
use ExUnit.CaseTemplate
setup_all tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)
# we are setting :auto here so that the data persists for all tests,
# normally (with :shared mode) every process runs in a transaction
# and rolls back when it exits. setup_all runs in a distinct process
# from each test so the data doesn't exist for each test.
Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, :auto)
{:ok, tenant} = MyApp.Tenant.create(%{name: "example"})
on_exit fn ->
# this callback needs to checkout its own connection since it
# runs in its own process
:ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)
Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, :auto)
# we also need to re-fetch the %Tenant struct since Ecto otherwise
# complains it's "stale"
tenant = MyApp.Tenant.get!(tenant.id)
MyApp.Tenant.delete(tenant)
:ok
end
[tenant: tenant]
end
end
Now i can use the tenant in my tests:
defmodule MyApp.MyTest do
use MyApp.ConnCase
use MyApp.TenantCase
test "foo", %{tenant: tenant} do
...
end
end