运行 混合测试时如何避免 ExUnit.start() 错误

How do I avoid ExUnit.start() error when running mix test

当我在我的项目中 运行 mix test 时,出现以下错误,我不明白为什么:

$ mix test
Compiling 2 files (.ex)

== Compilation error in file lib/myproject_web/controllers/email_controller_test.ex ==
** (RuntimeError) cannot use ExUnit.Case without starting the ExUnit application, please call ExUnit.start() or explicitly start the :ex_unit app
    expanding macro: ExUnit.Case.__using__/1
    lib/myproject_web/controllers/email_controller_test.ex:2: MyProjectWeb.EmailControllerTest (module)
    (elixir 1.10.1) expanding macro: Kernel.use/2
    lib/myproject_web/controllers/email_controller_test.ex:2: MyProjectWeb.EmailControllerTest (module)

我已经在 lib/ 中有一个 test_helper.exs 文件调用 ExUnit.start()。我的设置很不寻常,因为我希望在模块旁边进行测试,而不是在单独的 test 文件夹中。

原来这个错误来自扩展名为 .ex 而不是 .exs 的测试文件。使用 .ex 然后 mix 尝试在 运行 测试之前用其他所有东西编译它然后抱怨因为 ExUnit.start() 在编译时没有被调用。

如果使用 .exs 扩展名,那么文件不会被编译,而是在 test_helpers.exs 调用 ExUnit.start() 之后由 mix test 编译 运行。

如果您阅读 mix test 的文档:

This task starts the current application, loads up test/test_helper.exs and then requires all files matching the test/**/*_test.exs pattern in parallel.

你是对的 .exs 文件没有被编译,但是即使它们被编译也不是问题。测试是 运行 作为避免重复编译的脚本,因为它们每次都会获得随机顺序,具有不同的输出编译。

任务首先编译所有文件,然后启动 ExUnit 并展开 *_test.exs 脚本中的所有宏。要证明这一点,请查看 this piece of code:

defmacro __using__(opts) do
    unless Process.whereis(ExUnit.Server) do
      raise "cannot use ExUnit.Case without starting the ExUnit application, " <>
              "please call ExUnit.start() or explicitly start the :ex_unit app"
    end

这意味着在您使用 use ExUnit.Case 的文件中,ExUnit 服务器应该在解释这些脚本时启动并 运行ning。

一般来说,在您的情况下,即使更改为 .exs,您的测试也不应该成功,因为 default configuration 的测试路径是:

 defp default_test_paths do
    if File.dir?("test") do
      ["test"]
    else
      []
    end

相反,您应该调用测试:

mix test test/some/particular/file_test.exs