使用Ecto在Elixir中的测试中有时会出现怪异的错误

时间:2019-06-19 12:28:04

标签: elixir ecto ex-unit

错误:

14:18:04.259 [error] GenServer MyApp.Receiver.Handlers terminating
** (Ecto.Query.CastError) deps/ecto/lib/ecto/repo/queryable.ex:382: value `1234` in `where` cannot be cast to type :string in query:

from c0 in MyApp.DB.Client,
  where: c0.client_id == ^1234,
  select: c0

    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir) lib/enum.ex:1431: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/repo/queryable.ex:138: Ecto.Repo.Queryable.execute/4
    (ecto) lib/ecto/repo/queryable.ex:18: Ecto.Repo.Queryable.all/3
    (ecto) lib/ecto/repo/queryable.ex:67: Ecto.Repo.Queryable.one/3
    (my_app) lib/my_app/db/db_impl/db_impl.ex:54: MyApp.DBImpl.add_update_client/1
    (my_app) lib/my_app/receiver/receiver_handlers.ex:23: MyApp.Receiver.Handlers.handle_cast/2
    (stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:711: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:add_update_client, %{client_id: 1234, client_pid: #PID<0.408.0>}}}
State: %{}
@doc """
Client connects or reconnects
"""
def add_update_client(client) do
  %{client_id: client_id} = client

  # This is the line causing the error
  client_db = DB.Client |> Repo.get_by(client_id: client_id)

  create_update_client(client_db, client)
end
defmodule MyApp.DB.Client do
  use Ecto.Schema

  schema "client" do
    field :client_id, :string
    field :client_pid, :binary

    timestamps()
  end

  # This says how you can change a record
  def changeset(client, params \\ %{}) do
    client
    |> Ecto.Changeset.cast(params, [:client_id, :client_pid])
    # Use validation if need be
    |> Ecto.Changeset.validate_required([:client_id, :client_pid])
  end

  def update_client_pid_changeset(client, params \\ %{}) do
    client
    |> Ecto.Changeset.cast(params, [:client_pid])
    # Use validation if need be
    |> Ecto.Changeset.validate_required([:client_pid])
  end

end

defmodule MyApp.Repo.Migrations.CreateClient do
  use Ecto.Migration

  def change do
    create table(:client) do
      add :client_id, :string
      add :client_pid, :binary

      timestamps
    end
  end
end

我尝试将发生故障的线路更改为此,但仍然收到相同的错误:

client_db = Repo.one(from c in DB.Client,
  where: c.client_id == type(^client_id, :string)
)

我用于client_id的值是数字字符串,例如“ 1234”,但有时 Ecto不能弄清楚。这仅在1/10左右的测试中发生。据我所知,当代码正常运行时,它一直都有效。 我怀疑这与测试运行的顺序有关,但我不确定是否与之相关。 还有其他人有类似的问题和可能的解决方案吗?

编辑: 我认为正在发生的事情是代码“ 1234”中的某个地方变成了1234。尽管如此,我也不知道是如何发生或为什么发生的。我从json文件中提取这些值,所以我认为它可能来自解析器,但这似乎没有发生。同样,所有值都可以毫无问题地插入数据库。一次更新就触发了变更集错误,因此代码以某种方式将字符串解析为数字。

已解决: 我以前编写的doctest触发了插入数据库的操作,并且我在doctest中使用1234而不是正确使用“ 1234”,所以这一直是我的错误。

1 个答案:

答案 0 :(得分:0)

如何尝试:

  

在插值时,您可能需要明确告诉Ecto什么   是要插值的预期类型:

age = "18"
Repo.all(from u in "users",
          where: u.age > type(^age, :integer),
          select: u.name)

https://hexdocs.pm/ecto/Ecto.Query.html