Reputation: 11029
I'm trying to test a belongs to association in Elixir.
Say I have two models, a Product and a ProductType. Products belong to a product type.
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
Here's what I have in my test file:
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
I'm basically creating a product type, creating a product, fetching the product record from the database and verifying that the type is the same as one I created.
Is this a reasonable approach?
For posterity's sake, here is a cleaner test without using changesets:
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
To test this association, you can essentially forgo casting and validations.
Upvotes: 8
Views: 4903
Reputation: 5181
A great reference for testing an Ecto association is the actual tests Ecto uses for testing associations. You can check it out on their GitHub.
https://github.com/elixir-ecto/ecto/blob/master/test/ecto/schema_test.exs
Here's an example:
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
Upvotes: 4
Reputation: 1462
I would not test this explicitly at all - you're basically testing Ecto here.
This sort of thing I usually test implicitly in e.g. a controller test, where you post something and then make sure that the correct data was created in the DB.
If you want to have a unit test for that, you need to think about what exactly you want to compare. It should be enough to test that the inserted product type's id is the same as the inserted product's product_type_id, but that feels weird because then it's more obvious that you're just testing ecto functionality here.
Upvotes: 3