2017-04-13 36 views
0

我有一個控制器:Phoenix:控制器測試與視圖測試?

defmodule ParrotApi.MeetupController do 
    use ParrotApi.Web, :controller 
    alias ParrotApi.Meetup 

    def index(conn, _params) do 
    one_hour_ago = Timex.now 
        |> Timex.shift(hours: -1) 
        |> Timex.to_unix 
    meetups = from(m in Meetup, where: m.timestamp >= ^one_hour_ago) 
       |> Repo.all 
       |> Repo.preload(:topic) 
    render conn, meetups: meetups 
    end 
end 

與此控制器一個觀點:

defmodule ParrotApi.MeetupView do 
    use ParrotApi.Web, :view 

    def render("index.json", %{ meetups: meetups }) do 
    render_many(meetups, ParrotApi.MeetupView, "meetup.json") 
    end 

    def render("meetup.json", %{ meetup: meetup }) do 
    %{ 
     id: meetup.id, 
     timestamp: meetup.timestamp, 
     topic: meetup.topic.title, 
    } 
    end 
end 

我在寫我的第一個控制器測試:

defmodule ParrotApi.MeetupControllerTest do 
    use ParrotApi.ConnCase 
    alias ParrotApi.Meetup 
    alias ParrotApi.Topic 
    alias ParrotApi.Repo 

    require Logger 

    describe "#index" do 
    test "returns future meetups" do 
     topic_title = "Is Jesus your savior?" 
     future_time = Timex.now 
        |> Timex.shift(minutes: 1) 
        |> Timex.to_unix 
     {:ok, topic} = Topic.changeset(%Topic{}, %{title: topic_title}) |> Repo.insert 
     {:ok, meetup} = Meetup.changeset(%Meetup{}, %{timestamp: future_time, topic_id: topic.id}) |> Repo.insert 

     conn = build_conn() 
     conn = get conn, meetup_path(conn, :index) 

     assert json_response(conn, 200) == [ 
     %{ 
      "id" => meetup.id, 
      "timestamp" => future_time, 
      "topic" => topic_title, 
     } 
     ] 
    end 

它傳遞。但是......這對我來說是一種視圖測試嗎?它正在測試視圖所操縱的裝飾/呈現響應。所以我不知道該如何做我的視圖測試。

有沒有辦法只測試了render conn, meetups: meetups響應,然後在我的控制器測試目前提取的東西到視圖測試?或者這是測試事情的錯誤方法?

+0

這可能是相當主觀的,但是當我做控制器的測試中,我大多隻是確保我得到我期待的迴應。例如當我期望頁面加載時的'200'狀態代碼,'302'用於當用戶未登錄時的重定向等。然後在我的視圖測試中,我確保某些內容被加載和顯示。 –

+0

你願意展示一個例子嗎? – Edmund

回答

1

雖然我認爲測試的最佳實踐有很多關於開發商的意見和偏見,我非常同意您的測試是它的責任之外,並實際JSON結構應在視圖測試測試測試的東西。

個人而言,我更喜歡測試json響應的內容以及控制器測試中的響應狀態,但是您的測試對「jsons結構如何」而非「內容是什麼」做出了非常有力的假設, 。

你通常會離開JSON創建到JSON的創造者(視圖)和只關心「並不控制器渲染它應該呈現什麼呢?」

如果我總結了用一句話測試最重要的東西,那將是:「在你的腦海裏制定你想測試的東西,然後試着讓你的測試代碼完全像一樣讀取」。所以基本上我想我的測試讀取像這樣:

我期待一個json編碼的響應與狀態碼200所有未來的聚會。

test "returns future meetups" do 
    topic_title = "Is Jesus your savior?" 
    future_time = Timex.now 
       |> Timex.shift(minutes: 1) 
       |> Timex.to_unix 
    {:ok, topic} = Topic.changeset(%Topic{}, %{title: topic_title}) |> Repo.insert 
    {:ok, meetup} = Meetup.changeset(%Meetup{}, %{timestamp: future_time, topic_id: topic.id}) |> Repo.insert 

    conn = build_conn() 
    conn = get conn, meetup_path(conn, :index) 

    future_meetups_json = MeetupView.render("index.json", %{meetups: MeetupQuery.future_meetups()}) 

    assert conn.status == 200 
    assert conn.response_body == future_meetups_json 
end 

隨着聚會的查詢在一個單獨的方法侷促,可以seperately進行測試,以確保它真的只返回聚會它應該返回與實際視圖測試可以在視圖測試來完成:)