Reputation: 683
I'm currently testing controller that uses the function create_zone that depends on a function that retrieves a user to associates said user to a zone and then creates a participant entry that is only an association table of both entries.
def create_zone(attrs \\ %{}, user_id) do
user = Accounts.get_user!(user_id)
with{:ok, %Zone{} = zone} <- %Zone{}
|> Zone.changeset(attrs,user)
|> Repo.insert()
do
create_participant(zone,user)
end
end
And I would like to test it using ExUnit but the problem is that the testing framework tries to search a non existent record in the database.
** (Ecto.NoResultsError) expected at least one result but got none in query:
from u in Module.Accounts.User,
where: u.id == ^1
How could I mock or create it just for testing purposes?
Upvotes: 1
Views: 965
Reputation: 4885
You can write a simple factory module that uses Ecto to insert into the database. The test will be wrapped in a database transaction and rolled back automatically thanks to the Ecto.Sandbox.
defmodule Factory do
def create(User) do
%User{
name: "A. User",
email: "user_#{:rand.uniform(10000)}@mail.com"
}
end
def create(Zone) do
%Zone{
# ... random / default zone attributes here...
}
end
def create(schema, attrs) do
schema
|> create()
|> struct(attributes)
end
def insert(schema, attrs \\ []) do
Repo.insert!(create(schema, attrs))
end
end
Then in your test custom attributes are merged with the factory defaults, including associations.
test "A test" do
user = Factory.insert(User, name: "User A")
zone = Zones.create_zone(user.id)
assert zone
end
See chapter 7 of what's new in ecto 2.1 for a more detailed explanation.
Upvotes: 1
Reputation: 9841
Don't mock it, create it with ex_machina: https://github.com/thoughtbot/ex_machina
Mocking is discouraged in Elixir: http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ (you don't really need to read it now, but in case you are want to mock some external resource, read it).
Upvotes: 1