Search⌘ K

Testing Update Operation

Explore how to write effective tests for update operations in Ecto queries. Understand how to balance test coverage and maintenance by focusing on key fields, using factories to set up test data, and asserting changes correctly. This lesson guides you through success and error test cases to ensure data integrity during updates.

We'll cover the following...

Testing update is a combination of the testing for the create and read functions.

The Update function

Let’s first look at the function we’re going to test:

Elixir
#file path -> testing_ecto/lib/users/users.ex
#add this code at the indicated place mentioned in comments of testing_ecto/lib/users/users.ex
#in the playground widget
def update(%User{} = existing_user, update_params) do
existing_user
|> User.update_changeset(update_params)
|> Repo.update()
end

Like create/1, we can see that this function is a very lightweight wrapper around calls to the schema’s changeset function (update_changeset/2 in this case) and then to Repo.update/1.

Tests

Testing the update function will be similar, but we’ll need to insert an existing user to be updated by the code.

Let’s write our success test first:

Elixir
#file path -> testing_ecto/test/users/users_test.exs
#add this code at the indicated place mentioned in comments of testing_ecto/test/users/
#users_test.exs in the playground widget
test "success: it updates database and returns the user" do
existing_user = Factory.insert(:user)
params =
Factory.string_params_for(:user)
|> Map.take(["first_name"])
assert {:ok, returned_user} = Users.update(existing_user, params)
user_from_db = Repo.get(User, returned_user.id)
assert returned_user == user_from_db
expected_user_data =
existing_user
|> Map.from_struct()
|> Map.drop([:__meta__, :updated_at])
|> Map.put(:first_name, params["first_name"])
for {field, expected} <- expected_user_data do
actual = Map.get(user_from_db, field)
assert actual == expected,
"Values did not match for field: #{field}\nexpected: #{
inspect(expected)
}\nactual: #{inspect(actual)}"
end
refute user_from_db.updated_at == existing_user.updated_at
assert %DateTime{} = user_from_db.updated_at
end

Let’s take a look at this test:

  • The test uses the factory to insert a user in line 6.
  • In the instruction starting from line 8, the test is creating a parameter map to pass in. It’s using the
...