1

I'm using ex_machina to create fixture for my unit-tests.

I'm saving some records to the database using ExMachina insert(:comment) but my assertions are wrong because ExMachina always load relations and it's not the case when I'm fetching with Ecto and not calling Repo.preload.

Let's say I have 2 factories comment and user:

def user_factory do
  %User{
    name: "some name"
  }
end

def comment_factory do
  %Comment{
    content: "some content",
    user: build(:user)
  }
end

when I'm testing

  test "should retrieve last comment" do
    comment = fixture(:comment)
    assert Comment.get_last_comment() == comment
  end

Assertion if failing because on the left I have

%Comment{
    ...,
    content: "some content",
    user: #Ecto.Association.NotLoaded<association :user is not loaded>
}

and on the right

%Comment{
    ...,
    content: "some content",
    user: %User{ name: "some name" }
}

I'm trying to avoid:

  • using Repo.preload on my left records because sometimes there are quite a lot of dependencies

  • testing each property individually

Thanks by advance for your help

samidarko
  • 590
  • 7
  • 20

1 Answers1

2

I've tackled this problem by defining a equal_records function in test/support/data_case.ex that just compares the type of the structs and the ids of the records:

def equal_records(%{__struct__: t1, id: id1}, %{__struct__: t2, id: id2}) do
  t1 == t2 and id1 == id2
end

def equal_records(_, _), do: false

Usage:

test "should retrieve last comment" do
  comment = fixture(:comment)
  assert equal_records(Comment.get_last_comment(), comment)
end

To also test lists of records, add these functions too:

def equal_records([], []), do: true
def equal_records([h1 | t1], [h2 | t2]) do
  equal_records(h1, h2) and equal_records(t1, t2)
end
zwippie
  • 15,050
  • 3
  • 39
  • 54
  • That's an approach but I prefer the one suggested here https://stackoverflow.com/a/49997873/2035262 by https://stackoverflow.com/users/2035262/mudasobwa – samidarko Aug 14 '18 at 02:12