如何为ExUnit实现“assert_difference”

时间:2016-09-28 10:20:55

标签: testing elixir ex-unit

我想测试一个函数如何在数据库中改变某些东西。我正在努力使用与以下ActiveSupport::TestCase测试用例相当的ExUnit:

test "creates a database record" do
  post = Post.create title: "See the difference"
  assert_difference "Post.published.count" do
    post.publish!
  end
end

RSpec版本更优雅,因为它使用了lambdas,我认为它可以移植到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

是否有比这更优雅(阅读:功能)的方式:

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

1 个答案:

答案 0 :(得分:1)

您可以使用宏来获取Ruby附近的TestUnit和RSpec示例:

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

但我不会使用它,除非它将被用于 lot ,否则这只会使代码更难以跟随每个人(可能),除了作者。如果您确实使用它,您可能希望将其移动到另一个模块并将其导入测试模块中。