在测试外生2.0 SQL沙箱错误

问题描述 投票:8回答:3

我最近升级我的凤凰项目外生2.0.2。我有一个使用Task.Supervisor.async_nolink就其自己的线程一些更新到数据库的一些代码。我收到的时候我的测试运行下面的错误(只发生在我的测试)

[error] Postgrex.Protocol (#PID<0.XXX.0>) disconnected: **
(DBConnection.ConnectionError) owner #PID<0.XXX.0> exited while 
client #PID<0.XXX.0> is still running with: shutdown

现在,我想我明白发生了什么:该外生沙盒连接池被重新签入前分贝交易完成。按照文档(至少我的方式阅读)来绕过这些东西的方式是使用一个共享的连接池:Ecto.Adapters.SQL.Sandbox.mode(MyApp.Repo, {:shared, self()})该我做的。不幸的是,这是行不通的。

如何设置我的测试,这样就不会出现这个错误?

elixir phoenix-framework ecto
3个回答
6
投票

如果任何人遇到这种情形,我直接从语言的作者何塞·Valim的答案回在此:

是的,你对问题的理解是正确的。它发生,因为在测试过程中,谁拥有该连接的一个,已经退出,但任务仍然使用它的连接。使用{:共享,自()}不能解决问题,因为测试仍然拥有连接,你只是分享它含蓄。

解决的方法是保证任务的测试退出之前完成。这可以通过调用Process.exit来完成(task_pid,:杀)。如果你不知道这个任务的PID,你可以调用Task.Supervisor.which_children(NameOfYourTaskSupervisor)返回所有PID你然后遍历并杀死他们。但是,如果你这样做的方式,测试不能同时运行(如你可以杀了另一个测试开始后的任务)。


5
投票

今天我有同样的问题,我想我已经找到了一个可能的解决方案以使测试同时运行。

我使用这里描述的技术:http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/,同时运行测试替代Task.Supervisor。

代替:

Task.Supervisor.async_nolink(TaskSupervisor, fn -> (...) end)

我正在做:

@task_supervisor Application.get_env(:app, :task_supervisor) || Task.Supervisor
# ...
@task_supervisor.async_nolink(TaskSupervisor, fn -> (...) end)

然后我定义TestTaskSupervisor

defmodule TestTaskSupervisor do
  def async_nolink(_, fun), do: fun.()
end

config :app, :task_supervisor, TestTaskSupervisor添加config/test.exs

这样一来,我敢肯定,任务将同步运行和测试过程之前完成。


0
投票

这个问题最终由药剂v1.8.0和db_connection V2.0.4解决。见https://twitter.com/plataformatec/status/1091300824251285504https://elixirforum.com/t/problem-asynchronizing-ecto-calls/19796/8

如果使用较新的除上述药剂和DBConnection的版本,测试应该工作开箱没有任何错误。

© www.soinside.com 2019 - 2024. All rights reserved.