1

我想编写测试来验证我的应用程序中的 SQL 查询返回的数据是否符合某些约束:即返回值以插入降序排列。在应用程序中,我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 层存在一些批处理或惰性。

我能想到的“最简单”的解决方案是某种方式来“强制”在呼叫站点进行交易,所以我可以:timer.sleep(1)在它们之间,给我不同的字段(因此是问题标题)但有XY 问题inserted_at的风险我我愿意接受其他建议。谢谢!

4

2 回答 2

1

由于您似乎正在尝试测试 get_in_order_of_recency 方法而不是数据库/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 添加为第二列以按降序排序,这将强制执行您要查找的顺序。

于 2019-01-01T03:30:42.640 回答
-1

您正在测试Ecto您的 SQL 驱动程序。你不应该这样做,它是零意义的。

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

Ecto.Query.order_by/3作品; 如果您不信任它,最好使用其他库。

于 2019-01-02T06:27:31.830 回答