2013-05-02 101 views
-1

我正在寫一個保齡球分數計算器,我試圖設置RSpec測試,但由於某些原因,我無法讓我的測試正常工作。Rspec實例變量和控制器測試

players_controller_spec.rb:

require 'spec_helper' 

describe PlayersController do 
    let(:player_names) { ["player1", 
         "player2", 
         "player3", 
        "player4"] } 

    describe "POST bowl" do 
    before(:each) do 
     @game = Game.create! 
     player_names.each do |name| 
     Player.create!(:name => name) 
     end 
     @game.players = Player.all 
     Player.all.each do |player| 
     (0..9).each do |number| 
      player.frames << Frame.create(:number => number) 
     end 
     end 
    end 
    describe "for the player's third bowl" do 
     before(:each) do 
     @game.players[@game.current_player].frames[9].update_attributes({:number => 9, :first_bowl => "X", :second_bowl => "X", :score => 20}) 
     @game.update_attributes({:current_player => 0, :current_frame => 9}) 
     end 

     describe "if the bowl is a number score" do 
     before(:each) do 
      post :bowl, {:score => "5", :id => @game.id} 
     end 

     it "should update the player's score" do 
      @game.players[@game.current_player].frames[@game.current_frame].score.should == 25 
     end 
     end 
    end 
    end 
end 

players_controller.rb

def bowl 
    @game = Game.find(params[:id]) 
    @score = params[:score] 

    @current_player = @game.current_player 
    @current_frame = @game.current_frame 
    @player = @game.players[@current_player] 

    @frame = @player.frames[@current_frame] 

    if @frame.first_bowl.nil? 
     @frame.first_bowl = @score 
     if @score == "/" 
     raise "Error" 
     end 
     if @score == "X" && @frame.number == 9 
     @frame.bonus = 2 
     end 
     @frame.score = (/\A[0-9]\z/ === @score ? @score.to_i : 10) 
    elsif @frame.second_bowl.nil? 
     @frame.second_bowl = @score 
     if @frame.score + @score.to_i > 10 
     raise "Error" 
     end 
     if @score == "X" 
     if @frame.number != 9 || (@frame.number == 9 && @frame.first_bowl != "X") # can't be a spare has to be number or strike 
      raise "Error" 
     end 
     end 
     if @score == "/" && @frame.number == 9 
     @frame.bonus = 1 
     end 
     if /\A[0-9]\z/ === @score 
     @frame.score += @score.to_i 
     elsif @score == "/" 
     @frame.score = 10 
     elsif @score == "X" 
     @frame.score = 20 
     end 
    elsif @frame.third_bowl.nil? 
     @frame.third_bowl = @score 
     if @frame.number != 9 
     raise "Error" 
     end 
     @frame.bonus = nil 
     @frame.update_attributes({:score => (/\A[0-9]\z/ === @score ? @frame.score + @score.to_i : @frame.score + 10)}) 
    else 
     raise "Error" 
    end 
    @frame.save 

    if @game.current_frame > 0 
     @prev_frame = @player.frames[@frame.number-1] 

     if @prev_frame.nil? 
     @prev_frame = Frame.create(:number => @game.current_frame-1) 
     @player.frames << @prev_frame 
     @player.frames = @player.frames.sort_by { |f| f.number } 
     end 

     update_scores 
    end 

有問題的規範是players_controller_spec.rb,並在試驗開始我創建4名玩家全新的遊戲和每個玩家10幀。在每次測試之前,我將設定某個框架的值,以適合我想要測試的內容。上面的測試是一個例子,我想確保在最後一幀的第三個碗上保齡球得分5正確地更新得分。但是,即使在調試器中,我發現在框架中更新了分數(當我在控制器方法中進行調試時),一旦我返回到Rspec測試,它不起作用。它預計25但得零。有什麼我錯過了實例變量如何在規格和控制器之間傳輸?

+0

如果您專注於一個案例並專門爲該測試發佈代碼,那麼您更有可能得到一個很好的答案,這樣我們就有必要關注。發佈鏈接到您的代碼庫的方式太開放了:發佈您詢問的特定案例的代碼(即從第393行開始),所以我們不必去追捕它。 – 2013-05-02 06:14:40

+0

明白了 - 我添加了規範代碼的特定片段。 – tanookiben 2013-05-02 08:26:46

回答

0

所以首先沒有'轉移'。控制器和示例是2個完全獨立的對象,每個對象都有其自己的實例變量(您可以使用assigns規範助手來檢索控制器實例變量的值)。

這不是你問題的根本原因。即使在控制器執行之前,您也可以擁有一個@game實例變量,這是您感興趣的遊戲。但是,使用activerecord時,每次執行Game.find時,都會收到單獨的ruby對象(對應於相同的數據庫行)。一旦從數據庫加載該行,它就不會注意到其背後的數據庫發生了更改。

可以重新裝載@game.reload

對象作爲一個方面說明這種東西是更容易,如果大部分邏輯被向下推入你的車型之一,而不是坐在控制器開始工作。