我是一个完全陌生的Elixir,但是当使用Node时,我们做了很多早期回报,但我遇到了一些问题,使早期回报般的代码在我的集成测试中工作。这是我的问题。
我的控制器中有这样一个方法,它接收一个JSON作为param,我需要验证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
我到底做错了什么?
在Elixir中,If-statements是很少见的:模式匹配是比较习惯的。 执行流的分叉可能很难遵循,你会发现 "早期返回 "在最好的情况下可能有点混乱,或者在最坏的情况下是一个反模式。
考虑重构你的代码,在函数参数中进行模式匹配。这不仅消除了对验证函数的需求(因为模式匹配只有在这些键存在的情况下才会成功),它允许你定义多个子句的 create/2
函数。 这实际上给你提供了2条执行路径:一条用于当 key
和 type
参数,而当参数不存在时,则执行另一个函数。
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
记住:更具体的匹配必须先进行--执行将被派往匹配成功的第一个函数。