【问题标题】:How to test models with required associations如何测试具有所需关联的模型
【发布时间】:2016-06-22 14:48:50
【问题描述】:

使用 Ecto 2.0:

defmodule PlexServer.BoardInstanceTest do
  use PlexServer.ModelCase

  alias PlexServer.BoardInstance

  @valid_attrs %{board_pieces: [%PlexServer.BoardTileInstance{x: 0, y: 0}], empire: %PlexServer.EmpireInstance{}}
  @invalid_attrs %{}

  test "changeset with valid attributes" do
    changeset = BoardInstance.changeset(%BoardInstance{}, @valid_attrs)
    assert changeset.valid?
  end
end

defmodule PlexServer.BoardInstance do
  use PlexServer.Web, :model

  alias PlexServer.BoardTileInstance

  schema "board_instances" do  
    belongs_to :empire, PlexServer.EmpireInstance
    has_many :board_pieces, BoardTileInstance

    timestamps
  end

  @required_fields ~w()
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
      |> cast(params, @required_fields, @optional_fields)
      |> cast_assoc(:board_pieces, required: true)
      |> cast_assoc(:empire, require: true)
  end
end

我的测试失败了

** (RuntimeError) 不支持使用 cast/3 转换关联,请改用 cast_assoc/3

查看文档说 cast_assoc/3 需要在 cast/3 之后调用,所以我很确定我错过了使该测试正常工作所必需的一些东西。

编辑:更新了我的代码,现在收到一个新错误:

** (Ecto.CastError) 期望参数是一张地图,得到:%PlexServer.BoardTileInstance{__meta__: #Ecto.Schema.Metadata<:built>, fleets: #Ecto.Association.NotLoaded<association :fleets is not loaded>, id: nil, inserted_at: nil, system: #Ecto.Association.NotLoaded<association :system is not loaded>, updated_at: nil, x: 0, y: 0}

我猜我的@valid_attrs 格式不正确?

【问题讨论】:

  • 尝试从@required_fields 中删除empireboard_pieces 并为:empire 添加cast_assocrequired: true
  • 我按照您的建议进行了更改,@Dogbert,但不幸的是我仍然遇到问题。
  • 您在进行这两项更改后遇到了同样的错误?
  • 试试这个:@valid_attrs %{board_pieces: [%{x: 0, y: 0}], empire: %{}}.
  • @Dogbert 成功了!非常感谢。如果您想创建一个答案,我会接受它。我猜 cast_assoc 根本不希望传入 Ecto.Schema?

标签: elixir ecto ex-unit


【解决方案1】:
  1. 您无需将关联名称传递给castvalidate_required。您应该将其从@required_fields 中删除。 cast_assoc 将处理将这些字段转换为结构,如果您通过 required: true,将验证它们是否存在。 (没有读过上面cmets的朋友,请看revision 1 of the question的上下文。)

  2. @valid_attrs 应该是一个法线贴图,就像你在 Phoenix 控制器的函数中得到的 params 一样。 cast_assoc 将处理将原始映射转换为结构。所以,改变

    @valid_attrs %{board_pieces: [%PlexServer.BoardTileInstance{x: 0, y: 0}], empire: %PlexServer.EmpireInstance{}}
    

    @valid_attrs %{board_pieces: [%{x: 0, y: 0}], empire: %{}}
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2018-02-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多