2010-11-18 108 views
2

我試圖測試我的控制器的create操作。我正在使用Devise進行身份驗證,並使用before_filter方法限制對登錄用戶訪問create操作。這是我的控制器的相關部分。Rails 3中使用Devise和RSpec測試控制器

class RawDataSetsController < ApplicationController 
    before_filter :authenticate_user!, :except => [:show, :index, :download] 

    def create 
    @raw_data_set = current_user.raw_data_sets.build(params[:raw_data_set]) 
    if @raw_data_set.save 
     redirect_to @raw_data_set 
    else 
     render "new" 
    end 
    end 
end 

在我的測試案例中,我想確保登錄的用戶可以創建一個RawDataSet。我認爲我已經根據this博客帖子上的說明嘲笑了經過驗證的用戶。

require 'spec_helper' 
describe RawDataSetsController do 

    include Devise::TestHelpers 

    def mock_users(stubs={}) 
    @user ||= mock_model(User, stubs).as_null_object 
    end 

    def log_in_test_user 
    attr = { :username => "Foobar", :email => "[email protected]" } 
    #mock up an authentication in warden as per http://www.michaelharrison.ws/weblog/?p=349 
    request.env['warden'] = mock(Warden, :authenticate => mock_users(attr), 
             :authenticate! => mock_users(attr), 
             :authenticate? => mock_users(attr)) 
    end 

    before do 
    @rds = Factory(:raw_data_set) 
    end 

    describe "POST 'create'" do 

    before do 
     @attr = { 
     :organism_name => "Beef Jerky", 
     :mass_spec_type => "My Stomach", 
     } 
    end 

    describe "logged in user" do 
     it "should create a raw_data_set when the user is logged in" do 
     log_in_test_user 
     lambda do 
      post :create, :raw_data_set => @attr 
     end.should change(RawDataSet, :count).by(1) 
     end 
    end 
    end 
end 

運行這個測試案例導致以下錯誤:

1) RawDataSetsController POST 'create' logged in user should create a raw_data_set when the user is logged in 
Failure/Error: post :create, :raw_data_set => @attr 
undefined method `user_url' for #<RawDataSetsController:0x0000010175af88> 
# ./app/controllers/raw_data_sets_controller.rb:7:in `create' 

我對這個錯誤感到困惑。經過更多檢查,@raw_data_set不是RawDataSet模型類的實例,而是用戶?這就是當我p @raw_data_set

#<User:0x807a06a4 @name="User_1002"> 

魔鬼正在發生什麼?我究竟做錯了什麼?如何使用經過驗證的用戶在我的控制器上測試創建操作?

回答

1

編輯(完全錯誤的第一刪除嘗試)

調用as_null_object主要用來告訴模擬接受沒有存根的所有消息,就回到自己。所以,當你調用

current_user.raw_data_sets.build(params[:raw_data_set])

這通常會返回關聯到current_userRawDataSet,而不是你爬不起來current_user

因此,當您嘗試呼叫重定向,傳遞@raw_data_set時,您將它傳遞給模擬而不是RawDataSet實例,因此錯誤地調用user_url

我認爲處理這個問題的方法只是使用一個真正的用戶(或工廠),並在其上設計出Devise方法。所以,你的mock_users成爲(例如):

def mock_users(stubs={}) 
    @user = User.create(stubs) 
    end 

現在current_user會怎麼做構建,並通過關聯保存。

純粹主義者會告訴你嘲笑和剔除一切,直到你在臉上變得藍色。擰緊 - 你有更好的事情要做。 :)

解決此問題的另一種方法是測試是否收到構建消息,而不檢查保存是否成功。假設你的模型測試將驗證通過該關聯節省的工作 - 爲什麼再次在控制器中測試?

+0

問題是,來自控制器的這一行:@raw_data_set = current_user.raw_data_sets。build(params [:raw_data_set])正在我的測試中返回一個User類的實例,這完全不是我想要的。它應該是RawDataSet類的一個實例,並重定向到RawDataSets#show。 – jergason 2010-11-18 21:27:59

+0

謝謝你的幫助。我仍然得到RSpec的支持,所以這非常有幫助。 – jergason 2010-11-20 06:14:10

相關問題