2011-06-22 43 views
0

我真的很努力學習rspec :(所以我希望你可以給我一點幫助,在控制器中創建一個非常簡單的動作。我想使用Rspec :: mocks for這一點,因爲我認爲這是做而不必測試時打的數據庫的方式簡單的rspec問題

我有一個的before_filter:?

def find_project 
    @project= Project.find_by_id(params[:project_id]) 
end 

的創建操作是這樣的:

def create 
    @batch = Batch.new(params[:batch]) 
    @batch.project = @project 

    if params[:tasks] 
    params[:tasks][:task_ids].each do |task_id| 
     @batch.tasks << Task.find(task_id) 
    end 
    end 

    if @batch.save 
    flash[:notice] = "Batch created successfully" 
    redirect_to project_batch_url(@project, @batch) 
    else 
    render :new 
    end 
end 

我是r最後懷疑是什麼時候提到@batch.project = @project我該如何定義@project?而且也是整個params[:tasks][:task_ids].each部分..雅..幾乎整個事情:(

對不起,這個新手的問​​題 - 希望你們能夠幫助或至少點我在正確的方向:)

感謝

+0

加斯帕:我覺得你的問題是有點難以理解。你到底有什麼困難?你可以換個說法來補充說明嗎? – iwasrobbed

回答

0

控制器規範的思想是檢查操作是否設置實例變量,以及根據需要重定向/渲染。要設置規範,通常會創建一個對象或模擬對象,設置屬性/存根,然後調用該動作,並在必要時傳遞參數散列。

因此,例如(空氣代碼)

describe MyController do 
    before(:each) do 
    @project = mock_model(Project) 
    Project.stub(:find_by_id) {@project} 
    @batch = mock_model(Batch) 
    Batch.stub(:new) {@batch} 
    end 

    it "should redirect to project_batch_url on success" do 
    @batch.stub(:save) {true) 
    post :create, :batch => { :some_key => :some_value }, :tasks => { :task_ids => [1,2,3] } 
    response.should redirect_to(project_batch_url(@project,@batch)) 
    end 

    it "should render :new on failure" do 
    @batch.stub(:save) {false) 
    post :create, :batch => { :some_key => :some_value }, :tasks => { :task_ids => [1,2,3] } 
    response.should render_template("new") 
    end 
end 

你可以找到很多有關此方面的RSpec Rails docs的更多信息。

0

使用BDD可幫助您定義接口。因此,如果您的控制器希望項目創建一個批處理並添加一些任務標識,那麼「編寫您希望擁有的代碼」。在控制器的實踐中,這意味着試圖將邏輯推出控制器並進入你的模型。測試模型往往更直觀,肯定比測試控制器更快。

下面是從視「mockist」點一些可能的規格(未經測試):

# controller spec 
describe BatchesController do 
    def mock_project(stubs={}) 
    @mock_project ||= mock_model(Project, stubs) 
    end 

    def mock_batch(stubs={}) 
    @mock_batch ||= mock_model(Batch, stubs) 
    end 

    context "POST create" 
    it "calls #create_batch_and_add_tasks on the project" 
     mock_project.should_receive(:create_batch_and_add_tasks).with(
     :batch => { :name => 'FooBatch' }, 
     :task_ids => [1,2,3,4] 
    ) 
     Project.stub(:find).and_return(mock_project) 

     post :create, :batch => { :name => 'FooBatch' }, :tasks => { :task_ids => [1,2,3,4] } 
     # consider changing your params to :batch => { :name => 'FooBatch', :task_ids => [1,2,3,4] } 
    end 

    it "redirects to the project_batch_url on success" do 
     mock_project(:create_batch_and_add_tasks => mock_batch(:save => true)) 
     Project.stub(:find) { mock_project } 
     post :create, :these_params => "don't matter because you've stubbed out the methods" 
    end 

# controller 
def create 
    @batch = @project.create_batch_and_add_tasks(
      :batch => params[:batch], 
      :task_ids => params[:tasks].try([:tasks_ids]) 
      ) 
    if @batch.save 
    ... 
+0

單片眼鏡:感謝您的答案:)並感謝幫助我保持我的控制器瘦! :) 這是使用rspec進行控制器測試的正確方法嗎?或者你對此有何看法? – Jesper

+0

我不認爲有一個'正確的'方法。當你習慣RSpec時,你會發現你喜歡如何測試。查看更多RSpec Book。 – monocle