设置事务隔离级别时的Phoenix / Elixir测试

时间:2019-01-13 13:07:13

标签: postgresql elixir phoenix-framework ecto postgrex

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

SELECT
  date
, SUM(total_customer)
, array_agg(product_category ORDER BY product_category)
, array_agg(total_qty        ORDER BY product_category)
, SUM(total_price)
FROM ( 
        SELECT 
          date(order_date)
        , count(customer_id) as total_customer
        , product_category
        , sum(quantity) as total_qty
        , sum(total_price) as total_price
        FROM public."CURRENT_WP_SALES"
        WHERE order_status = 'sale'
        GROUP BY date(order_date), product_category
) T
GROUP BY date
ORDER BY date

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

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

  # do some queries

end)

我想知道我是在做根本上是错误的事情,还是在缺少我所需要的测试环境?

谢谢!

2 个答案:

答案 0 :(得分: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

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

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

这将使您运行路径中可序列化的测试,并且仍然使用沙箱。

答案 1 :(得分:0)

问题是出于测试目的,所有测试都包装在一个事务中,因此可以回滚它们,因此您不会用大量的旧测试数据污染数据库。根据您编写测试的方式,这可能会导致应该通过的失败以及应该失败的通过。

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

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,了解本质上要求相同问题的人。