![](/img/trans.png)
[英]Which functions are called 'under the hood' when using Ecto.Repo in elixir
[英]Test coverage in repo class using Ecto in Elixir
我在 Elixir 中有一个非常简单的应用程序,它使用 Ecto,在 Postgres 的表中运行 SELECT 查询。 表名是“person”,有两列:“name”和“age”。
这是应用程序:
/ecto_app
|-application.ex
|-repo.ex
应用程序.ex:
defmodule EctoApp.Application do
use Application
require Logger
@impl true
def start(_type, _args) do
children = [
EctoApp.Repo
]
opts = [strategy: :one_for_one, name: EctoApp.Supervisor]
Logger.debug("Starting Ecto App")
Supervisor.start_link(children, opts)
end
end
回购.ex:
defmodule EctoApp.Repo do
use Ecto.Repo,
otp_app: :ecto_app,
adapter: Ecto.Adapters.Postgres
import Ecto.Query
require Logger
def get_people() do
query = from p in "person",
select: [p.name, p.age]
result= EctoApp.Repo.all(query)
Logger.debug(result)
end
end
我正在使用这两个库:
[
{:ecto_sql, "~> 3.0"},
{:postgrex, ">= 0.0.0"}
]
该应用程序运行良好,但问题是我想为回购进行单元测试,但我不知道如何模拟 Postgres 连接,因为我不想启动 Postgres 实例来运行测试。
有没有人知道如何模拟或我可以使用哪个库来“模拟”与 Postgres 的连接,这样我就可以在回购 class 上进行测试?
谢谢!
您不需要像模拟其他功能那样模拟 PostGres 连接。 这是因为 PostGres 可以将操作包装在一个可撤销的事务中。 要点是您的测试使用真实连接并对真实数据库发出真实请求,但该数据库专用于测试并通过特殊适配器发出查询。 这是迄今为止为数据库支持的应用程序实现测试覆盖率的最常见方法; 尝试模拟数据库连接会使脆弱的测试充满误报,因此通常不会这样做,尤其是当对真实数据库发出所有请求如此简单时。
以下是在您的代码中促进这一点的重要部分:
# config/dev.exs
config :my_app, MyApp.Repo,
pool: DBConnection.ConnectionPool,
database: "something_dev",
# ... etc...
# config/test.exs
config :my_app, MyApp.Repo,
pool: Ecto.Adapters.SQL.Sandbox,
database: "something_test",
# ... etc...
Repo
。 这就是将操作包装在事务中的原因,因此您可以安全地重新运行测试而无需过多清理。 一个好的地方是在setup callback内部,它在模块中的每个测试之前运行:defmodule MyApp.SomeTest do
use ExUnit.Case # you may require async: false
alias Ecto.Adapters.SQL.Sandbox
alias MyApp.Repo
setup do
Sandbox.checkout(Repo)
end
describe "get_people/0" do
test "select" do
# insert fake records here
assert [] = Repo.get_people()
end
end
end
还有几点建议:
您的get_people/0
function,如所写,不会返回result
。 请记住,Elixir 依赖于隐式返回,因此它返回上次操作的结果。 在您的情况下,返回的内容将是调试语句的结果,这只是一个:ok
而不是您期望的result
。
不要忘记您可能需要对测试数据库运行迁移——这不是自动发生的事情。 您可以在mix.exs
中创建一个别名以在测试之前执行mix ecto.migrate
,或者您可以只记得对测试数据库运行MIX_ENV=test mix ecto.drop
等。
您经常会发现自动构建数据“夹具”(即具有适当形状的假记录)很有帮助。 ex_machina package 是执行此操作的便捷方法,但无论您使用 package 还是滚动自己的固定装置,您的测试都需要使用您期望的任何测试记录来准备数据库,作为标准中“安排”步骤的一部分“安排-行动-断言”测试方法。
如果你的情况确实需要你模拟数据库连接,那么我会推荐一个依赖于一种“依赖注入”的简单模式,例如,你可以将Repo
模块覆盖为 function 参数或从配置中提取的东西,例如
def get_people(repo \\ Repo)
query = from p in "person",
select: [p.name, p.age]
repo.all(query)
end
我建议在容器中运行 PostgreSQL,然后使用 Ecto Sandbox。 https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html
ecto带有自己的测试套件,并且有专门的文档介绍如何使用 Ecto 进行测试。
Ecto.Adapters.SQL.Sandbox
将用于测试,但无法避免启动实际的数据库实例,主要是因为使用模拟连接进行测试意义不大。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.