joshua.aug
How to rollback db changes between tests
I have multiple tests in one file. I want to create users at the beginning of each test and roll back those db changes at the end of each test.
At the top of my file I have this:
use Teiserver.DataCase, async: true
which references this module
defmodule Teiserver.DataCase do
use ExUnit.CaseTemplate
using do
quote do
alias Teiserver.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query
import Teiserver.DataCase
end
end
@doc """
Sets up the sandbox based on the test tags.
"""
def setup_sandbox(tags) do
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Teiserver.Repo, shared: not tags[:async])
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
end
setup tags do
setup_sandbox(tags)
:ok
end
@doc """
A helper that transforms changeset errors into a map of messages.
assert {:error, changeset} = Accounts.create_user(%{password: "short"})
assert "password is too short" in errors_on(changeset).password
assert %{password: ["password is too short"]} = errors_on(changeset)
"""
def errors_on(changeset) do
Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
Regex.replace(~r"%{(\w+)}", message, fn _, key ->
opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
end)
end)
end
end
However it seems like my changes are persisted between tests.
Also test_helper.exs has this
ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(Teiserver.Repo, :manual)
alias Teiserver.Repo
alias Central.Helpers.GeneralTestLib
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo, sandbox: false)
if not GeneralTestLib.seeded?() do
GeneralTestLib.seed()
Teiserver.TeiserverTestLib.seed()
end
Ecto.Adapters.SQL.Sandbox.checkin(Repo)
How do I make it so any db changes are rolled back after each test?
You can see the video in this link where I run the same test multiple times and it will just randomly fail eventually.
First Post!
dimitarvp
What’s wrong with using setup? It gets invoked before each test. And whatever you create in your each test should be automatically rolled back by Ecto at the end of each test. Have you tried?
As an experiment to maybe increase understanding, try putting that file in your project (f.ex. directly inside test/):
defmodule Stuff.AndStuffTest do
setup do
IO.puts("before each test")
%{stuff: :you_need}
end
test "one thing", context do
IO.inspect(context)
end
test "another thing", context do
IO.inspect(context)
end
end
…and run mix test test/stuff_and_stuff_test.exs, and see what output you are getting.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









