2011-04-13 58 views
0

假設我有以下作用:如何用複雜的查詢測試控制器操作?

def index 
    @posts = Post.joins(:tags).where(:tags => {:id => params[:tag_id]}) 
end 

它暴露@posts的觀點,這將顯示每一個崗位與給定的標籤。

一切工作正常,但我堅持試圖找出測試它的最佳方法。

我真的不喜歡嘲諷,因爲它可能剎車測試,如果我改變該行:

@posts = Post.where(:tags => {:id => params[:tag_id]}).joins(:tags) 

我真的不想打數據庫,因爲它會降低試驗速度,但我正在考慮將查詢提取到模型內部的一個方法,並在那裏測試它是否是唯一的方法。

編輯:是的,我知道我可以在這種情況下使用Tag.find(params[:tag_id]),但這並不是問題是什麼。我只是不想在查詢中引入另一個模型,並且更難解釋偏離實際問題的焦點,即:我們是否應該在控制器中保留複雜的查詢?如果是這樣,測試它的最好方法是什麼?

+2

一個附帶的問題,爲什麼不:@ posts = Tag.find(params [:tag_id])。posts。這感覺更自然,很少在那裏測試。 – tokland 2011-04-13 21:03:46

+4

複雜的查詢應該是您的模型中的範圍,而不是控制器中的範圍。 – apneadiving 2011-04-13 21:04:04

+0

@tokland這只是一個帶有「連接」和「where」的查詢的例子,而不是真正的代碼。我只是試圖簡化它,因此很容易解釋它的作用。 – 2011-04-13 21:15:17

回答

0

因此,根據評論提取到模型是最好的事情。這就是我做的:

post.rb:

class Post 
    scope :tagged_as, lambda {|tag_id| where(:tag_id => tag_id)} 
end 

posts.yml:

one: 
    title: Post 1 
    tags: one, three 

two: 
    title: Post 2 
    tags: two, three 

post_test.rb:

test 'find by tag' do 
    posts = Post.tagged_as(tags(:one)) 
    assert_includes posts, posts(:one) 
    refute_includes posts, posts(:two) 
end 
+0

爲什麼你會重塑聯想而不是做'tag.posts'?更何況你要求一個標籤ID,但提供一個標籤對象。 – 2011-04-18 19:47:16

+0

你可以做Tag.find(tag_id).posts。 – methyl 2011-04-18 19:49:56

+0

@Rein請參閱我在評論中給托克蘭的答案。這不是真正的代碼。我只是試圖做一個簡單的查詢,所以每個人都會關注控制器和複雜的查詢測試問題。不幸的是,我認爲結果恰恰相反,所以我要編輯這個問題。 – 2011-04-18 19:54:20

0

這就是我喜歡做的事情。通常,我喜歡在我的測試中集成數據庫測試(儘管有些人會不同意,我個人喜歡它)。我會創建像3個工廠(:後),也許一些標籤作爲虛擬數據,然後我會打電話給控制器,並檢查收到的@posts是我所期望的。

相關問題