Testing the Happy Path for Create

Learn how to write a happy path test for the create endpoint.

Let’s take a look at the create endpoint. This is the endpoint hit by the form rendered by our previous endpoint for new.

Controller

Let’s take a look at the code and discuss what we’ll need to test:

Press + to interact
#file path -> lib/not_skull_web/controllers/user_controller.ex
def create(conn, %{"user" => user_params}) do
case Accounts.create_user(user_params) do
{:ok, user} ->
Email.send_welcome(user)
conn
|> put_session(:user_id, user.id)
|> put_flash(:info, "Your account was created successfully!")
|> redirect(to: Routes.user_path(conn, :show, user))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end

There’s branching logic in this function, depending on the success of Accounts.create_user(user_params). As a result, we know that we’ll need at least two tests, a happy path test and an error test.

Happy path test

There are four new code elements that we haven’t tested before:

  1. Sending an email (an outside call as a side effect)
  2. Setting values in the session
  3. Setting the flash
  4. Redirecting a call.

Let’s write our happy path test first since it’s where we’ll cover these. Open up the test file user_controller_test.exs and add a new describe block and test as follows:

Press + to interact
#file path -> test/not_skull_web/controllers/user_controller_test.exs
describe "POST /users" do
test "success: creates_user, redirects to show page when user is created",
%{conn: conn} do
params = Factory.atom_params(:user)
expect_email_to(params.email)
conn = post(conn, Routes.user_path(conn, :create), user: params)
assert %{id: id} = redirected_params(conn)
assert redirected_to(conn) == Routes.user_path(conn, :show, id)
assert %{"user_id" => ^id} = get_session(conn)
assert get_flash(conn, :info) =~ "success"
user_from_db = Repo.get(User, id)
fields_to_check = Map.keys(params) -- [:password]
assert_values_for(
expected: params,
actual: user_from_db,
fields: fields_to_check
)
assert user_from_db.password
end
end

Let’s see the details of the test:

  • It inherits a Plug.Conn from the test setup.
  • On line 5, we’re getting valid parameters from our factory.
  • Line 7 calls out to a custom helper function, expect_email_to/1, which sets up an expectation that we’ll attempt to send the email. When we’re done reviewing this test, we’ll circle back and look at the code of that helper function. For now, we can
...