Elixir/Phoenix: 如何在不使用 Ecto 的情况下对模型进行单元测试?

Elixir/Phoenix: How to do unit tests for models without using Ecto?

我正在构建一个 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

我该如何处理?

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

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

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

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

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 将允许您定义在所有使用模块中可用的助手。

简短回答:不用 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。如果您的模型测试用例之间有足够的共享代码,这可能是个好主意。