Best practices for testing associations of the Elixir Ecto model

I am trying to verify membership in an Elixir association.

Say I have two models: Product and ProductType. Products are related to the type of product.

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 is 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 basically create a product type, create a product, retrieve the product from the database and verify that the type is the same as the one I created.

Is this a smart approach?

EDIT

For posterity, this is a cleaner test without using change sets:

 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 connection, you can significantly refuse castings and validations.

+6
source share
2 answers

I would not test this explicitly - you mainly test Ecto here.

I usually test such things implicitly, for example, a controller test, where you publish something, and then make sure that the correct data has been created in the database.

If you want to have a unit test for this, you need to think about what exactly you want to compare. It is enough to verify that the identifier of the inserted product type matches the inserted product product_type_id, but this seems strange, because then it is more obvious that you are simply checking the functionality of ecto here.

+4
source

A great reference for testing Ecto associations is the actual tests that Ecto uses to test associations. You can check it out on your github.

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

Here is 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 
+1
source

All Articles