I'd like to test how a function changes something in the database. I'm struggling with an ExUnit equivalent of the following ActiveSupport::TestCase
test case:
test "creates a database record" do
post = Post.create title: "See the difference"
assert_difference "Post.published.count" do
post.publish!
end
end
The RSpec version is more elegant and, because of its use of lambdas, something I thought was portable to Elixir/ExUnit.
it "create a database record" do
post = Post.create title: "See the difference"
expect { post.publish! }.to change { Post.count }.by 1
end
Is there a more elegant (read: functional) way to do it than this:
test "creates a database record", %{conn: conn} do
records_before = count_records
post(conn, "/articles")
records_after = count_records
assert records_before == (records_after - 1)
end
defp count_records do
MyApp.Repo.one((from a in MyApp.Article, select: count("*"))
end
You can use macros to get something close to the TestUnit and RSpec examples from Ruby:
defmacro assert_difference(expr, do: block) do
quote do
before = unquote(expr)
unquote(block)
after_ = unquote(expr)
assert before != after_
end
end
defmacro assert_difference(expr, [with: with], do: block) do
quote do
before = unquote(expr)
unquote(block)
after_ = unquote(expr)
assert unquote(with).(before) == after_
end
end
test "the truth" do
{:ok, agent} = Agent.start_link(fn -> 0 end)
assert_difference Agent.get(agent, &(&1)) do
Agent.update(agent, &(&1 + 1))
end
{:ok, agent} = Agent.start_link(fn -> 0 end)
assert_difference Agent.get(agent, &(&1)), with: &(&1 + 2) do
Agent.update(agent, &(&1 + 2))
end
end
But I wouldn't use it unless it's going to be used a lot or else this would only make the code harder to follow for everyone (possibly) except the author. If you do use it though, you might want to move it to a different module and import that in your test modules.