早期 return 无法在 elixir/phoenix 中进行集成测试

Early return not working in integration tests in elixir/phoenix

我对 Elixir 完全陌生,但是在使用 Node 时我们做了很多早期的 returns,但我在制作早期的 return 代码时遇到了一些问题在我的集成测试中。这是我的问题:

我的控制器中有这个方法,它接收一个 JSON 作为参数,我需要验证 JSON 是否包含一些属性(键和类型),如果不包含我想要的向客户端发送错误而无需执行方法的其余部分。当我使用 Insomnia 或 Postman 发出请求时,这非常有效,但它在我的集成测试中不起作用。即使条件为假,条件下面的代码也会执行。

这是我的方法:

def create(conn, body) do
    if !PayeeContext.check_for_required_fields(body), do: conn
      |> send_resp(400, "Please provide Key and Type parameters")

    %{"key" => key} = body
    %{"type" => type} = body

    validation_func = PayeeContext.validation_map(type)

    case validation_func.(key) do
      {:ok, _} ->
        conn |> send_resp(200, "Request created successfully")
      {:error, message} -> conn |> send_resp(400, message)
    end
  end

这是我的测试

test "returns 400 if Key prop is missing", %{conn: conn} do
      params = %{
        key: "44187221816",
        account: %{
          account_type: "checking_account",
          account_number: "00028363-6",
          branch: "0001"
        },
        owner: %{
          name: "Eve Montalvão"
        }
      }

      response = conn |> post(Routes.payee_path(conn, :create, params))

      assert response.status == 400
    end

和我的PayeeContext.check_for_required_fields

  def check_for_required_fields(fields) do
    Enum.all?(@required_fields, fn field -> Map.has_key?(fields, field) end)
  end

我做错了什么?

If 语句在 Elixir 中很少见:模式匹配更加地道。执行流程的分叉很难遵循,您会发现 "early returns" 充其量可能有点混乱,或者最坏的情况下是一种反模式。

考虑重构代码以在函数参数中进行模式匹配。这不仅消除了对验证函数的需要(因为模式匹配只有在这些键存在时才会成功),它还允许您定义 create/2 函数的多个子句。这有效地为您提供了 2 个执行路径:一个用于 keytype 参数存在的情况,另一个用于不存在的情况。

def create(conn, %{"key" => key, "type" => type}) do

    validation_func = PayeeContext.validation_map(type)

    case validation_func.(key) do
      {:ok, _} ->
        conn |> send_resp(200, "Request created successfully")
      {:error, message} -> conn |> send_resp(400, message)
    end
end

def create(conn, _) do
  send_resp(conn, 400, "Please provide Key and Type parameters")
end

记住:更具体的匹配必须先进行——执行将被分派到匹配成功的第一个函数。