【问题标题】:Ecto 2.0 + MySQL: cleaning fixtures in testsEcto 2.0 + MySQL:在测试中清理固定装置
【发布时间】:2016-12-16 17:22:00
【问题描述】:

我在 Elixir Phoenix 项目中使用 Ecto 2.0 和 MySQL。 根据 Ecto2.0 documentationMySQL 不支持并发测试,所以我想我应该使用 ExUnit.Case 而不是使用 ExUnit.Case, async: true,这样测试就不会同时运行。

在我的特定情况下,在我的测试中,我通过夹具将模型插入数据库中,一旦测试完成,夹具插入的模型仍保留在数据库中(由测试代码插入的模型本身会被清理)。我想删除夹具插入的模型。如果我这样做:

如果我这样做:

ExUnit.Case

setup do
  on_exit fn ->
    Repo.delete_all(ModelA)
    Repo.delete_all(ModelB)
  end
end

我明白了:

    ** (exit) exited in: GenServer.call(#PID<0.277.0>, {:checkout, #Reference<0.0.1.1885>, true, 15000}, 5000)
    ** (EXIT) shutdown: "owner #PID<0.276.0> exited with: shutdown"
stacktrace:
    (db_connection) lib/db_connection/ownership/proxy.ex:32: DBConnection.Ownership.Proxy.checkout/2

那么,如果我这样做:

ExUnit.Case, async: true

setup do
  on_exit fn ->
    Repo.delete_all(ModelA)
    Repo.delete_all(ModelB)
  end
end

它可以工作并且夹具数据在数据库中被清理。但是如果我指定ExUnit.Case, async: true,在运行所有测试时,我会遇到问题,因为测试同时在 MySQl 上运行。

【问题讨论】:

  • 你是从哪里插入灯具的?
  • fixtures 在 test/support 的一个模块中定义,它们被插入到 test 数据库中。测试正在使用和使用这些插入的固定装置,但它们不会自动清理。

标签: mysql elixir phoenix-framework ecto


【解决方案1】:

我认为您可能遗漏了一些错误消息。我不能肯定地说,但是 ecto2 的一个常见错误是所有权混淆了。使用 ecto2 现在有了进程所有权机制,它可以跟踪哪个事务属于哪个进程,以便可以进行并发状态测试。

但是,您需要告诉该映射。 on_exit 在与调用者不同的进程中运行,因此当 ecto 不知道哪个事务拥有它时,它会尝试访问数据库,从而引发错误。

您可能需要告诉 ecto(在您的 setup 块中)设置沙箱模式以允许任何进程在共享事务中访问数据库。由于您使用的是 MySQL,因此手动管理所有权是没有用的,因为您将永远不会运行并发数据库测试,因此最好为所有内容打开共享模式。

你可以这样做:

setup do
  Ecto.Adapters.SQL.Sandbox.mode(Perf.Repo, {:shared, self()})
end

我会将文档的一些相关部分粘贴到这篇文章中,但我不会这样做,这部分 ecto 的文档非常有帮助、详细和有用。 https://hexdocs.pm/ecto/Ecto.Adapters.SQL.Sandbox.html

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2016-11-15
    • 2010-11-17
    • 1970-01-01
    • 2014-01-12
    相关资源
    最近更新 更多