0

I usually check if my test returns the expected result like this:

company = company_fixture() # inserts a company in the database with default attributes
assert Profile.get_company!(company.id) == company

But this fails

     Assertion with == failed
     code:  assert Profile.get_company!(company.id) == company
     left:  %MyApp.Profile.Company{
              customers: [],
              employees: [],
              # more attributes, all matching
     }
     right: %Databaum.Profile.Company{
              customers: #Ecto.Association.NotLoaded<association :customers is not loaded>,
              employees: #Ecto.Association.NotLoaded<association :employees is not loaded>,
              # more attributes, all matching
            }

What is the recommended way of handling that? I want to obviously avoid preloading the associations in the test because that would avoid checking the fact that they are not preloaded in Profile.get_company!/1.

Joe Eifert
  • 1,306
  • 14
  • 29
  • Do you have left and right mixed up here? It says `get_company` is returning empty lists for the associations but the fixture is missing the associations, yet you say `get_company` doesn't preload. – Peaceful James Oct 08 '20 at 09:11
  • @PeacefulJames You are right, that is a little weird. Bad example. I hope it is still understandable. – Joe Eifert Oct 08 '20 at 10:08
  • 1
    I use something similar to this to remove associations from fixtures, it's very useful for this kind of scenarios https://stackoverflow.com/questions/49996642/ecto-remove-preload/49997873#49997873 – sbacarob Oct 08 '20 at 11:09

1 Answers1

1

I am afraid that your assert also fails because you are dealing with different structs. You could simply iterate through your struct and remove the fields with have %Ecto.Association.NotLoaded{} as value and then also remove those fields from your first struct, then assert both are equal, like this:

def remove_not_loaded_associations(struct_with_assoc, struct_without_assoc) do
  keys_to_remove = 
     struct_without_assoc
     |> Map.from_struct()
     |> Enum.filter(fn {_k, v} -> match?(%Ecto.Association.NotLoaded{}, v))
     |> Keyword.keys()

  map1 =
     struct_with_assoc
     |> Map.from_struct()
     |> Map.drop(keys_to_remove)

  map2 = 
     struct_without_assoc
     |> Map.from_struct()
     |> Map.drop(keys_to_remove)

  {map1, map2}
end

# ...
{map1, map2} = remove_not_loaded_associations(company, Profile.get_company!(company.id))
assert map1 == map2
Joe Eifert
  • 1,306
  • 14
  • 29
Julio GB
  • 427
  • 2
  • 12
  • 1
    I like the idea, but will probably rather make an `assert_equal_ignore_unloaded/2` method based on this that does not care about which side has the unloaded assocs. That seems cleaner to me. – Joe Eifert Oct 12 '20 at 15:57