2016-09-13 7 views
0

У меня есть подключаемый модуль для входа в систему, который очень похож на тот, который описан в this example by Thoughtbot. Я хочу добавить флеш-уведомление, когда пользователь перенаправляется. Он работает в браузере, но не при тестировании его изолированно.Доступ к сеансу и вспышка при модульном тестировании пользовательского подключаемого модуля

Штекер:

# In webs/plugs/require_login.ex 
defmodule MyApp.Plugs.RequireLogin do 
    import Plug.Conn 

    def init(opts), do: opts 
    if false # real user authentication omitted 
     conn 
    else 
     conn 
     |> Phoenix.Controller.put_flash(:error, "Login required.") 
     |> Phoenix.Controller.redirect(to: "/") 
     |> halt 
    end 
    end 
end 

Тест используется для этого:

defmodule MyApp.Plugs.RequireLoginTest do 
    use MyApp.ConnCase 

    test "user is redirected when authentication fails" do 
    conn = conn |> MyApp.Plugs.RequireLogin.call(%{}) 

    assert Phoenix.Controller.get_flash(conn, :error) == "Login required." 
    assert redirected_to(conn) == "/" 
    end 
end 

Сообщение об ошибке я получаю:

(ArgumentError) вспышка не извлекается, вызовите fetch_flash/2

Ошибка возникает в модуле plug, но если я прокомментирую строку put_session, ошибка переместится в мой тестовый файл.

Я понимаю, что хранилище сеансов настроено в lib/my_app/endpoint.ex, но как я могу повторно использовать эту конфигурацию, чтобы я мог тестировать модули?

Вот как плагин подключен к маршрутизатору:

# web/router.ex 
pipeline :browser do 
    # the Phoenix default 
end 

scope "/", MyApp do 
    pipe_through [:browser, MyApp.Plugs.RequireLogin] 
    resource "/protected", MyController, only: [:index] 
end 

ответ

1

Я смог решить это, используя bypass_through. Я не «запускал» запрос, например, Phoenix.ConnTest.get/3, что приводит к тому, что соединительный трубопровод не вызывается. Как только я добавил get/3, хэш-хэш стал доступен.

defmodule MyApp.Plugs.RequireLoginTest do 
    use MyApp.ConnCase 

    test "user is redirected when authentication fails", %{conn: conn} do 
    conn = conn 
      |> with_pipeline 
      |> MyApp.Plugs.RequireLogin.call(%{}) 

    assert Phoenix.Controller.get_flash(conn, :error) == "Login required." 
    assert redirected_to(conn) == "/" 
    end 

    defp with_pipeline(conn) do 
    conn 
    |> bypass_through(MyApp.Router, [:browser]) 
    |> get("/protected-uri") # any uri, bypass_through ignores the router rules 
    end 
end 
0

Редактировать
Первое, что приходит на ум, это вам не хватает параметров в тесте.

Ваш сопп генерируется, вероятно, где-то в вашем ConnCase:

setup tags do 
    ... 

    {:ok, conn: Phoenix.ConnTest.build_conn()} 
end 

И ваш тест должен выглядеть следующим образом:

test "user is redirected when authentication fails", %{conn: conn} do 

, чтобы иметь возможность использовать этот соед.



Второй вещь в том, что нет запроса (получить/сообщение и т.д.) в тесте, и ваши соппы вероятно, не проходят через :browser трубопровода.

+1

спасибо @amatalai. Моя пробная версия работает хорошо в сеансе браузера, просто не при запуске от модульного теста. Я уточнил свой вопрос, чтобы уточнить это. – carp

+0

@ carp обновил мой ответ также – amatalai

+0

ваш ответ заставил меня разобраться, как принудительно использовать конвейер в тесте. Я нашел 'bypass_through/3' - см. Мой ответ ниже. Благодаря! – carp