测试Elixir Ecto模型关联的最佳实践

时间:2015-11-26 00:33:52

标签: elixir phoenix-framework ecto

我试图在Elixir中测试属于该关联。

假设我有两个型号,一个产品和一个ProductType。产品属于产品类型。

defmodule Store.Product do
  use Store.Web, :model

  schema "products" do
    field :name, :string

    belongs_to :type, Store.ProductType, foreign_key: :product_type_id

    timestamps
  end

  @required_fields ~w(name product_type_id)

  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

defmodule Store.ProductType do
  use Store.Web, :model

  schema "product_types" do
    field :name, :string

    timestamps
  end

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

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

这是我在测试文件中的内容:

defmodule Store.ProductTest do
  use Store.ModelCase

  alias Store.Repo
  alias Store.Product
  alias Store.ProductType

  @valid_attrs %{
    name: "pickles", 
    product_type_id: 42,
  }

  @invalid_attrs %{}

  test "product type relationship" do
    product_type_changeset = ProductType.changeset(
      %ProductType{}, %{name: "Foo"}
    )
    product_type = Repo.insert!(product_type_changeset)

    product_changeset = Product.changeset(
      %Product{}, %{@valid_attrs | product_type_id: product_type.id}
    )
    product = Repo.insert!(product_changeset)

    product = Product |> Repo.get(product.id) |> Repo.preload(:type)
    assert product_type == product.type
  end
end

我基本上创建了一个产品类型,创建了一个产品,从数据库中获取产品记录并验证该类型与我创建的类型相同。

这是一种合理的方法吗?

修改

为了后人,这里是一个更清洁的测试,不使用变更集:

test "belongs to product type" do
  product_type = Repo.insert!(%ProductType{})
  product = Repo.insert!(%Product{product_type_id: product_type.id})
  product = Product |> Repo.get(product.id) |> Repo.preload(:type)
  assert product_type == product.type
end

要测试此关联,您基本上可以放弃投射和验证。

2 个答案:

答案 0 :(得分:4)

我根本不会明确地测试这个 - 你基本上在这里测试Ecto。

这种事我通常会在例如控制器测试,您在其中发布内容,然后确保在数据库中创建了正确的数据。

如果你想进行单元测试,你需要考虑你想要比较什么。它应该足以测试插入的产品类型的ID与插入的产品的product_type_id是否相同,但这感觉很奇怪,因为那时你更明显的是你只是测试这里有ecto功能。

答案 1 :(得分:1)

测试Ecto关联的一个很好的参考是Ecto用于测试关联的实际测试。你可以在他们的GitHub上查看。

https://github.com/elixir-ecto/ecto/blob/master/test/ecto/schema_test.exs

以下是一个例子:

test "belongs_to account" do
  association =
    %Ecto.Association.BelongsTo{cardinality: :one, defaults: [],
                                field: :account, on_cast: nil,
                                on_replace: :raise, owner: AccountUser,
                                owner_key: :account_id, queryable: Account,
                                related: Account, related_key: :id,
                                relationship: :parent, unique: true}

  assert AccountUser.__schema__(:association, :account) == association
end