elixir - 如何测试具有所需关联的模型

标签 elixir ecto ex-unit

使用 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) casting assocs with cast/3 is not supported, use cast_assoc/3 instead

查看文档说需要在cast/3之后调用cast_assoc/3,所以我很确定我缺少一些让这个测试正常工作所必需的东西。

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

** (Ecto.CastError) expected params to be a map, got: %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 格式不正确?

最佳答案

  1. 您无需将关联名称传递给 castvalidate_required。您应该将其从 @required_fields 中删除。 cast_assoc 将处理将这些字段转换为结构,并且如果您传递 required: true,将验证它们是否存在。 (对于那些没有阅读上述评论的人,请参阅 revision 1 of the question 了解上下文。)

  2. @valid_attrs 应该是一个法线贴图,就像您在 Phoenix Controller 的函数中获得的 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: %{}}
    

关于elixir - 如何测试具有所需关联的模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37959587/

相关文章:

elixir - 使用 Ecto 在运行时创建表

elixir - 如何在channelcase phoenix框架测试中清除邮箱

testing - 没有断言/反驳的 ExUnit,仅依赖于模式匹配?

elixir - 为什么范围相等在守卫中不起作用?

elixir - 如何使用 Phoenix 向特定套接字发送消息

Elixir:如何处理函数和 nil 值中的可选/默认参数?

elixir - 表单中的 date_select 失败, "<field> is invalid"

postgresql - 带有 tsrange 字段的 Ecto 模式

elixir - mix.compile 返回错误 (Mix) 无法编译 "src/gettext_po_parser.yrl"因为找不到应用程序 "parsetools"

unit-testing - Elixir /ExUnit : passing context from testcase to teardown/cleanup method (on_exit) possible?