2011-07-15 30 views
7

我使用Rails 3和RSpec 2.6.0。如何編寫一個RSpec控制器宏,該宏可以接受let或before塊中定義的參數?

不知道這是可能的,但這裏是我想要做什麼:

describe UsersController do 
    let(:user) { Fabricate :user } 
    describe "GET /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :get, :show, :id => user.id 
    end 
    describe "PUT /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :put, :update, :id => user.id 
    end 
end 

我想實現這樣的宏:

module ControllerMacros 
    def should_return_401_code_if_user_is_not_confirmed(verb, action, params = {}) 
    it "returns a 401 code if the user is not an admin" do 
     send verb, action, params 
     response.code.should == "401" 
    end 
    end 
end 

但運行這些功能我得到的時候錯誤undefined local variable or method 'user'。我試圖切換到在before塊中定義的@user變量,但它也不起作用。我懷疑這是因爲我不在示例塊中。

是否有可能傳遞給一個控制器通過let或在before塊定義的宏參數?

謝謝!

+0

您可能要考慮重構測試。在你的測試中有兩個條件並不是一個好主意 - 'if'的存在是一種測試氣味。您是在測試用戶是否已確認,還是隻是返回相應的代碼?如果是後者*設置*確認而不是檢查它。 –

回答

6

從rspec-users列表上的閱讀通過this thread看來答案是否定的。問題在於你的let/before變量沒有被初始化,直到宏的主體中的it塊,所以你不能將它們作爲參數引用到宏調用中。

我試圖在我正在工作的網站上做基本相同的事情。我正在使用的解決方案是使用將返回所需params散列的塊調用宏方法,然後在宏體中使用instance_eval來使用宏的範圍評估塊。

#spec 
... 
describe "GET /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :get, :show { {:id => user.id} } 
end 

#macro 
... 
def should_return_401_code_if_user_is_not_confirmed(verb, action, &params_block) 
    it "returns a 401 code if the user is not an admin" do 
    params = instance_eval &params_block 
    send verb, action, params 
... 
相關問題