首页 > 解决方案 > 早期返回不适用于 elixir/phoenix 的集成测试

问题描述

我对 Elixir 完全陌生,但是在使用 Node 时,我们会进行很多提前返回,但是在我的集成测试中让类似提前返回的代码工作时遇到了一些问题。这是我的问题:

我的控制器中有这个方法,它接收一个 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

我究竟做错了什么?

标签: elixirintegration-testingphoenixearly-return

解决方案


Elixir 中的 if 语句很少见:模式匹配更惯用。执行流程的分叉可能很难遵循,您会发现“提前返回”充其量可能有点令人困惑,或者最坏的情况是反模式。

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

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

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


推荐阅读