How to pass tests, that fails due to unloaded associations?
Asked Answered
R

1

7

I have written the following test.

test "list_users/1 returns all users in a tenant", %{tenant: tenant} do
  user = insert(:user, tenant: tenant)
  user_2 = insert(:user, tenant: tenant)

  assert Accounts.list_users(tenant) == [user_2, user]
end

I'm testing if i get all the users back within a tenant, to do that, i need to assign my factories the tenant, that i want to test against. The problem is that, when i assign the user the tenant, the association is now loaded. The returned users, does not, hence the test fails with the following diff..

tenant: #Ecto.Association.NotLoaded<association :tenant is not loaded>

vs

tenant: %MyApp.Accounts.Tenant{__meta__: #Ecto.Schema.Metadata<:loaded, "tenants">, domain: "pharma-13", id: 484, inserted_at: ~N[2017-06-14 15:10:42.125243], logo: "some_logo_path.png", name: "Pharma", updated_at: ~N[2017-06-14 15:10:42.125250]

Should i somehow unload the associations? I certainly don't want add preload to my function, just in order to pass the test.

Raptor answered 14/6, 2017 at 15:17 Comment(4)
I personally map both sides of assertion to obtain IDs, and I'm comparing thoseLindeberg
I ended up with that as well :-)Raptor
@PawełDawczak Could you give a concrete example as the answer to this question? I'm not sure I'm understanding this right: Do you only compare the ID's?Routinize
@Johannes, yes. Comparing to lists of IDs should sufficeLindeberg
P
1

It really depends on what you're trying to test. If you don't care about the association my suggestion would be to either assert on each property individually or run pattern matching assertions. This would be something along the lines of:

user_1 = insert(:user, tenant: tenant)
user_2 = insert(:user, tenant: tenant)

assert [found_user_2, found_user_1] = Accounts.list_users(tenant)
assert user_1.id == found_user_1.id
assert user_2.id == found_user_2.id

or

%{id: user_1_id} = insert(:user, tenant: tenant)
%{id: user_2_id} = insert(:user, tenant: tenant)

assert [%{id: ^user_2_id}, %{id: ^user_1_id}] = Accounts.list_users(tenant)

A third option could be to preload the associations IN THE TEST.

At the end of the day, there's no right or wrong answer here. It truly depends on what you want to test. The first option provides for a cleaner way of asserting multiple properties, the latter is more concise if you want to simply check the ids.

Pillsbury answered 20/5, 2021 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.