2016-11-23 40 views
1

从下面的代码,当我打电话conn.params["geo"],我得到以下错误:Plug.Conn.Unfetched没有实现访问行为

test/plugs/geoip_test.exs:4 
** (UndefinedFunctionError) function Plug.Conn.Unfetched.fetch/2 is undefined (Plug.Conn.Unfetched does not implement the Access behaviour) 
stacktrace: 
    (plug) Plug.Conn.Unfetched.fetch(%{:__struct__ => Plug.Conn.Unfetched, :aspect => :params, "geo" => "Mountain View, US", "ip" => "8.8.8.8"}, "geo") 

...

defmodule AgilePulse.Plugs.GeoIPTest do 
    use AgilePulse.ConnCase 

    test "returns Mountain View for 8.8.8.8" do 
    conn = build_conn 
    params = Map.put(conn.params, "ip", "8.8.8.8") 
    conn = Map.put(conn, :params, params) |> AgilePulse.Plugs.GeoIP.call(%{}) 

    assert conn.params["geo"] == "Mountain View, US" 
    end 

end 

defmodule AgilePulse.Plugs.GeoIP do 
    import Plug.Conn 

    def init(opts), do: opts 

    def call(%Plug.Conn{params: %{"ip" => ip}} = conn, _opts) do 
    geo = set_geo(ip) 
    params = Map.put(conn.params, "geo", geo) 
    Map.put(conn, :params, params) 
    end 

    def call(conn, _opts), do: conn 

    ... 

end 

可能有人开导我为什么这是失败的,什么是合适的解决方案? TY!

回答

3

简短的回答:更改此:

params = Map.put(conn.params, "ip", "8.8.8.8") 

要:

params = %{"ip": "8.8.8.8"} 

说明:Phoenix.ConnTest.build_conn/0返回Connparams设置为%Plug.Conn.Unfetched{}。通过使用上Map.put,你不复位的__struct__的价值,而只是添加一个新的关键:当你打电话params["geo"]

%Plug.Conn{ ..., 
params: %{:__struct__ => Plug.Conn.Unfetched, :aspect => :params, 
    "ip" => "8.8.8.8"}, ... } 

,花好月圆看到那params是一个结构,并试图调用fetch/2函数在结构的模块上,它不存在。若要将params重置为普通地图(以便Elixir在使用方括号语法时调用Map.get),则可以仅执行params = %{"ip": "8.8.8.8"}

+0

不错!所以在我的具体情况下,为了让测试通过,必须使用params =%{“ip”=>“8.8.8.8”}。但感谢你! – keruilin