Ecto утверждает #Ecto.Association.NotLoaded‹ассоциация: xyz не загружена›

Обычно я проверяю, возвращает ли мой тест ожидаемый результат, например так:

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

Но это не удается

     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
            }

Каков рекомендуемый способ справиться с этим? Очевидно, я хочу избежать предварительной загрузки ассоциаций в тесте, потому что это позволит избежать проверки того факта, что они не предварительно загружены в Profile.get_company!/1.


person Joe Eifert    schedule 08.10.2020    source источник
comment
У вас тут левое и правое перепуталось? В нем говорится, что get_company возвращает пустые списки для ассоциаций, но в приборе отсутствуют ассоциации, а вы говорите, что get_company не выполняет предварительную загрузку.   -  person Peaceful James    schedule 08.10.2020
comment
@PeacefulJames Вы правы, это немного странно. Плохой пример. надеюсь все же понятно.   -  person Joe Eifert    schedule 08.10.2020
comment
Я использую что-то подобное для удаления ассоциаций из приборов, это очень полезно для таких сценариев stackoverflow.com/questions/49996642/ecto-remove-preload/   -  person sbacarob    schedule 08.10.2020


Ответы (1)


Я боюсь, что ваше утверждение также не работает, потому что вы имеете дело с разными структурами. Вы можете просто перебрать свою структуру и удалить поля со значением %Ecto.Association.NotLoaded{}, а затем также удалить эти поля из своей первой структуры, а затем подтвердить, что оба равны, например:

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
person Julio GB    schedule 08.10.2020
comment
Мне нравится идея, но, вероятно, я сделаю на ее основе метод assert_equal_ignore_unloaded/2, который не заботится о том, на какой стороне находятся незагруженные ассоки. Мне это кажется чище. - person Joe Eifert; 12.10.2020