Phoenix Elixir:模拟内部函数

Phoenix Elixir: mock internal functions

我目前正在测试使用函数 create_zone 的控制器,该函数依赖于检索用户以将所述用户关联到区域然后创建仅是关联的参与者条目的函数 table 两个条目。

  def create_zone(attrs \ %{}, user_id) do
    user = Accounts.get_user!(user_id)

    with{:ok, %Zone{} = zone} <- %Zone{}
    |> Zone.changeset(attrs,user)
    |> Repo.insert()
    do
    create_participant(zone,user)
   end
  end

我想使用 ExUnit 对其进行测试,但问题是测试框架试图在数据库中搜索不存在的记录。

** (Ecto.NoResultsError) expected at least one result but got none in query:
   from u in Module.Accounts.User,
   where: u.id == ^1

我怎么能为了测试目的而模拟或创建它?

不要嘲笑它,用ex_machina创建它:https://github.com/thoughtbot/ex_machina

Elixir 中不鼓励模拟:http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/(你现在真的不需要阅读它,但如果你想模拟一些外部资源,请阅读它)。

您可以编写一个使用 Ecto 插入数据库的简单工厂模块。由于 Ecto.Sandbox.

,测试将被包装在数据库事务中并自动回滚
defmodule Factory do
  def create(User) do
    %User{
      name: "A. User",
      email: "user_#{:rand.uniform(10000)}@mail.com"
    }
  end

  def create(Zone) do
    %Zone{
       # ... random / default zone attributes here...
    }
  end

  def create(schema, attrs) do
    schema
    |> create()
    |> struct(attributes)
  end

  def insert(schema, attrs \ []) do
    Repo.insert!(create(schema, attrs))
  end
end

然后在您的测试中自定义属性与出厂默认值合并,包括关联。

test "A test" do
  user = Factory.insert(User, name: "User A")
  zone = Zones.create_zone(user.id)
  assert zone
end

请参阅 what's new in ecto 2.1 的第 7 章以获得更详细的解释。