【问题标题】:Rspec instance variables and controller testingRspec 实例变量和控制器测试
【发布时间】:2013-05-02 05:47:33
【问题描述】:

我正在编写一个保龄球得分计算器,并且我正在尝试设置 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

有问题的规范是 player_controller_spec.rb,在测试开始时,我正在创建一个有 4 个玩家的新游戏,每个玩家有 10 帧。在每次测试之前,我都会设置某个帧的值以适合我要测试的内容。上面的测试是一个示例,我想确保在最后一帧的第三个保龄球上保龄球得分为 5 正确更新了得分。但是,即使在调试器中我看到分数在框架中更新(当我在控制器方法中调试时),一旦我返回到 Rspec 测试,它就不起作用了。它预计为 25,但结果为零。关于如何在规范和控制器之间传输实例变量,我是否遗漏了什么?

【问题讨论】:

  • 如果您专注于一个案例并专门为该测试发布代码,那么您更有可能获得一个好的答案,这样我们就有了一些重点。将链接发布到您的代码库过于开放:发布您所询问的特定案例的代码(即从第 393 行开始),这样我们就不必去寻找它了。
  • 知道了 - 我添加了规范代码的特定 sn-p。

标签: ruby-on-rails rspec


【解决方案1】:

所以首先没有“转移”。控制器和示例是 2 个完全独立的对象,每个对象都有自己的实例变量(不过,您可以使用 assigns 规范助手来检索控制器实例变量的值)。

这不是问题的根本原因。即使在控制器执行之前,您也会有一个 @game 实例变量,这是您感兴趣的游戏。但是使用 activerecord,每次您执行 Game.find 时,您都会收到单独的 ruby​​ 对象(对应于同一数据库行)。一旦从数据库中加载了该行,它就不会注意到对其背后的数据库所做的更改。

你可以用@game.reload重新加载对象

作为旁注,如果大部分逻辑被推入您的一个模型而不是坐在控制器中,那么这种东西会更容易处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-22
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多