Search code examples
elixirphoenix-frameworkex-unit

Cleanup ExUnit test examples


I have the following tests in phoenix app:

defmodule TattooBackend.Web.API.V1.PasswordControllerTest do
  use TattooBackend.Web.ConnCase, async: true
  use Bamboo.Test

  alias TattooBackend.Web.Endpoint
  alias TattooBackend.Accounts.Account
  alias TattooBackend.Repo
  alias Phoenix.Token
  alias Comeonin.Bcrypt
  import TattooBackend.AuthenticationRequiredTest

  test "without passwords", %{conn: conn} do
    account = insert(:account)
    token   = Token.sign(Endpoint, "account_id", account.id)

    conn =
      conn
      |> put_req_header("authorization", "#{token}")
      |> post(api_v1_password_path(conn, :create))

    assert json_response(conn, 422)
  end

  test "with wrong password confirmation", %{conn: conn} do
    account = insert(:account)
    token   = Token.sign(Endpoint, "account_id", account.id)
    params  = %{password: "new-password", password_confirmation: "password"}

    conn =
      conn
      |> put_req_header("authorization", "#{token}")
      |> post(api_v1_password_path(conn, :create, params))

    assert json_response(conn, 422)
  end
end

Those lines are repeated over tests:

account = insert(:account)
token   = Token.sign(Endpoint, "account_id", account.id)

Any idea how to make it more DRY?


Solution

  • If you want to execute those two lines in all tests, you can put the repetitive code in a setup callback and then use pattern matching to fetch those in each test:

    defmodule TattooBackend.Web.API.V1.PasswordControllerTest do
      ...
    
      setup do
        account = insert(:account)
        token   = Token.sign(Endpoint, "account_id", account.id)
        [account: account, token: token]
      end
    
      test "without passwords", %{conn: conn, account: account, token: token} do
        conn =
          conn
          |> put_req_header("authorization", "#{token}")
          |> post(api_v1_password_path(conn, :create))
    
        assert json_response(conn, 422)
      end
    
      test "with wrong password confirmation", %{conn: conn, account: account, token: token} do
        params  = %{password: "new-password", password_confirmation: "password"}
    
        conn =
          conn
          |> put_req_header("authorization", "#{token}")
          |> post(api_v1_password_path(conn, :create, params))
    
        assert json_response(conn, 422)
      end
    end
    

    setup will execute its code before each test and then pass the account and token to each test.