【问题标题】:Phoenix / Elixir testing when setting isolation level of transaction设置事务隔离级别时的 Phoenix / Elixir 测试
【发布时间】:2019-01-13 13:07:12
【问题描述】:

我有一段看起来像这样的代码:

Repo.transaction(fn ->
  Repo.query!("set transaction isolation level serializable;")

  # do some queries

end)

在我的测试套件中,我不断遇到错误:

(Postgrex.Error) ERROR 25001 (active_sql_transaction): SET TRANSACTION ISOLATION LEVEL must be called before any query

我想知道我是否做错了什么,或者我是否缺少有关测试环境的某些内容。

谢谢!

【问题讨论】:

    标签: postgresql elixir phoenix-framework ecto postgrex


    【解决方案1】:

    不确定您是否仍在寻找这个问题的答案,但我找到了一个很好的解决方案。对于这种情况,我有这样的设置块:

    setup tags do
      :ok =
        if tags[:isolation] do
          Sandbox.checkout(Repo, isolation: tags[:isolation])
        else
          Sandbox.checkout(Repo)
        end
    
        unless tags[:async] do
          Sandbox.mode(Repo, {:shared, self()})
        end
    
        :ok
      end
    

    然后在可序列化事务路径中的测试中,您必须使用“可序列化”标记它,如下所示:

    @tag isolation: "serializable"
    test "my test" do
      ...
    end
    

    这将让您运行在路径中遇到可序列化的测试并且仍然使用沙盒。

    【讨论】:

      【解决方案2】:

      问题是出于测试目的,所有测试都包含在事务中,因此它们可以回滚,这样您就不会用大量旧测试数据污染数据库。这可能会导致本应通过的失败和本应失败的通过,具体取决于您编写测试的方式。

      您可以解决它,但它会再次污染您的测试数据库,您必须自己清理它:

      setup do 
        [Other set up stuff]
        Ecto.Adapters.SQL.Sandbox.checkin(MyApp.Repo) #This closes any open transaction, effectively.
        Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo, [sandbox: false]) # This opens a new transaction without sandboxing. 
      end
      

      如果您没有设置,则此设置任务会与失败的测试一起进入测试文件。如果您不进行checkin 调用,您将(很可能)在设置事务级别之前收到有关其他查询运行的错误,因为您在测试之前插入了一些东西。

      请参阅here 了解基本上提出相同问题的人。

      【讨论】:

      • 我原以为会是这样,而且会很好地解决问题,但不幸的是,我仍然遇到同样的错误。
      • 实际上,它可能会成功 - 可能回复得太早了。
      猜你喜欢
      • 1970-01-01
      • 2013-11-20
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 2012-04-22
      相关资源
      最近更新 更多