【问题标题】:Elixir/Phoenix: How to do unit tests for models without using Ecto?Elixir/Phoenix:如何在不使用 Ecto 的情况下对模型进行单元测试?
【发布时间】:2016-04-16 06:43:10
【问题描述】:

我正在构建一个 elixir phoenix 应用程序,使用自定义数据库适配器连接到 OrientDB。因此,我使用 --no-ecto 选项生成了基本应用程序,因为我没有使用 Ecto。

我正在构建自定义模型和自定义验证,但当然想要进行单元测试。

如果我尝试像这样在单元测试中包含 ModelCase:

defmodule App.UserTest do
  use App.ModelCase

end

我得到了错误

module App.ModelCase is not loaded and could not be found

这可能是因为它是 Ecto 的一部分。

如果我不包含它,代码稍后会失败,告诉我

undefined function test/2

我该如何处理?

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    简答:不要使用use App.ModelCase,而是使用use ExUnit.Case

    长答案。使用 Ecto 创建项目时,您会在 test/support 中获得三个不同的测试用例模板:

    • channel_case.ex
    • conn_case.ex
    • model_case.ex

    Case templates 用于定义可以在使用模板的每个测试中使用的函数。

    例如,model_case 为您定义了这个:

    using do
      quote do
        alias App.Repo
    
        import Ecto
        import Ecto.Changeset
        import Ecto.Query, only: [from: 1, from: 2]
        import App.ModelCase
      end
    end
    
    setup tags do
      unless tags[:async] do
        Ecto.Adapters.SQL.restart_test_transaction(App.Repo, [])
      end
    
      :ok
    end
    
    def errors_on(model, data) do
      model.__struct__.changeset(model, data).errors
    end
    

    quote do ... end 中的所有内容都在测试用例的开头注入。如果您不使用 Ecto,这根本没有用。第一行别名 repo,下一行导入 Ecto 模块(你没有)

    设置函数确保测试在事务中运行,当它们完成时可以回滚,errors_on 也是 Ecto 特定的。这就是为什么当你使用--no-ecto 运行时这个模块根本不存在。

    所以你有两个选择。您可以只使用ExUnit.Case,这是处理测试的标准方式(您可以通过使用mix 创建非Phoenix 应用程序来检查),或者您可以创建自己的App.ModelCase。如果您的模型测试用例之间有足够的共享代码,这可能是一个好主意。

    【讨论】:

    • 看起来您将应用的名称保留在 unless tags[:async] 块中。可能想将其更改为App.Repo,这样以后的人就不会感到困惑了。
    • model_case.ex 至少在 Elixir 1.5.2 中似乎已被 data_case.ex 取代
    【解决方案2】:

    App.ModelCase 不会使用--no-ecto 选项自动生成。

    它本身就是use ExUnit.CaseTemplate(See the CaseTemplate docs), 并将import App.ModelCase 注入到使用模块中。它还导入了一些特定于 ecto 的模块,但它们对您没有用处。

    在您的情况下,您可以在test/support/model_caseuse ExUnit.CaseTemplate 中定义App.ModelCase,并通过定义using 宏来定义要注入到 using 模块中的内容。

    只是为了让您了解您可能想做的一些事情,这里有一个 ecto-specific 版本示例:

    defmodule App.ModelCase do
      use ExUnit.CaseTemplate
    
      using do
        quote do
          alias App.Repo
    
          import Ecto
          import Ecto.Changeset
          import Ecto.Query, only: [from: 1, from: 2]
          import App.ModelCase
        end
      end
    
      setup tags do
        # Setup stuff you want to automatically do before tests 
      end
    
      def some_helper_function
        # helper function stuff goes here
        #
        # this function is available in all using modules because of 
        # the `import App.ModelCase` in the using macro.
      end
    end
    

    所以要么:

    1. 创建文件
    2. 删除与您的应用无关的内容
    3. 添加你自己的东西

    或者只是use ExUnit.Case 而不是use App.ModelCase。无论哪种方式都应该有效。

    use ExUnit.Case 更简单。 use App.ModelCase 将允许您定义在所有使用模块中都可用的助手。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2016-10-27
      • 2016-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多