允许 Ecto 在测试环境中立即查询 运行?

Allow Ecto queries to run immediately in a test environment?

我想编写测试来验证我的应用程序 return 数据中的 SQL 查询是否遵守某些约束:即 return 值以降序插入的形式呈现命令。在应用程序中,我在我的模式中使用 timestamps()inserted_at 字段包含到数据库中,并在我的查询中针对它进行查询 (SELECT … ORDER BY inserted_at DESC).

我的麻烦来自于我的测试:如果我有像

这样的测试代码
person1_params = %{name: "Tidehunter"}
{:ok, tidehunter} = People.create_person(person1_params)

person2_params = %{name: "Kunkka"}
{:ok, kunkka} = People.create_person(person2_params)

person3_params = %{name: "Windrunner"}
{:ok, windrunner} = People.create_person(person3_params)

而且我想对他们的订单做出断言,例如

people = People.get_in_order_of_recency()
assert Enum.at(people, 0).name == "Windrunner"

这失败了,尽管在手动测试中这一切似乎都有效。经检查,我发现所有三个记录的 inserted_at 是相同的。我试过添加 :timer.sleep() 调用,但它并没有改变结果,这表明 Ecto/Postgrex 层有一些批处理或惰性。

我能想到的 "simplest" 解决方案是 "force" 在呼叫站点发生交易的某种方式,因此我可以 :timer.sleep(1) 在它们之间,让我与众不同 inserted_at 字段(因此是问题标题),但冒着 XY problem 的风险,我愿意接受其他建议。谢谢!

由于您似乎正在尝试测试 get_in_order_of_recency 方法而不是 database/ecto 的日期时间功能,您可以为 <MYPROJ>.Repo 添加别名,然后执行类似以下操作:

Repo.insert!(%People{inserted_at: ~N[2019-01-01 00:00:10], name: "Tidehunter"})
Repo.insert!(%People{inserted_at: ~N[2019-01-01 00:00:11], name: "Kunkka"})
Repo.insert!(%People{inserted_at: ~N[2019-01-01 00:00:12], name: "Windrunner"})

在您的测试中而不是使用创建界面。这将允许您验证您的方法是否正确地按照您想要的顺序检索人员。

作为替代方案,考虑测试失败是合理的。当同时引入多个记录时,您想要的顺序不会得到维护。作为补救措施,将 id 添加为第二列以按降序排序,这将强制执行您正在查找的顺序。

您正在测试 Ecto 和您的 SQL 驱动程序。你不应该那样做,这毫无意义。

您可能想要在这里测试的唯一一件事(虽然我肯定它也是多余的)是 inserted_at 字段被填充。

Ecto.Query.order_by/3 有效;如果你不信任它,你最好使用其他库。