【问题标题】:Phoenix Elixir: mock internal functionsPhoenix Elixir:模拟内部函数
【发布时间】:2017-09-27 23:52:26
【问题描述】:

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

  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

我怎样才能模拟或创建它只是为了测试目的?

【问题讨论】:

  • 是否用例如模拟它github.com/eproxus/meck 不适合你?该函数是公开的,所以它应该可以工作。

标签: testing mocking elixir phoenix-framework ecto


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您可以编写一个使用 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章。

    【讨论】:

    • 谢谢。我最终使用了 ex_machina,它的功能基本相同,但界面更易于使用。
    猜你喜欢
    • 2017-03-16
    • 2018-12-18
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多