Ruby 如果调用了方法,则进行rspec测试

Ruby 如果调用了方法,则进行rspec测试,ruby,testing,rspec,Ruby,Testing,Rspec,我不知道如何编写一个可以运行的测试,它也不会在我的CL脚本中运行任何东西。当@counter为9时,它应该触发#平局游戏?但它不起作用@计数器初始化为0,并且每当玩家在游戏板上放置X或O时,计数器将递增1。我怎样才能测试一下@counter是9,它称之为tie_游戏?当它小于9时,它不会吗 def initialize(player1, player2) @player1 = player1 @player2 = player2 @rows = [[1, 2, 3], [

我不知道如何编写一个可以运行的测试,它也不会在我的CL脚本中运行任何东西。当@counter为9时,它应该触发#平局游戏?但它不起作用@计数器初始化为0,并且每当玩家在游戏板上放置X或O时,计数器将递增1。我怎样才能测试一下@counter是9,它称之为tie_游戏?当它小于9时,它不会吗

def initialize(player1, player2)
    @player1 = player1
    @player2 = player2
    @rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

    @wins = [1, 2, 3], [4, 5, 6], [7, 8, 9], 
        [1, 4, 7], [2, 5, 8], [3, 6, 9],
        [1, 5, 9], [3, 5, 7]

    @selected_numbers = []
    @counter = 0
end

def increment_counter
    @counter += 1

    if @counter == 9
        tie_game?
    end
end

def tie_game?
    puts "The game was a tie. Nicely played #{@player1} & #{@player2}!"
    play_again  
end
我试过这个:你能解释一下为什么它不起作用吗

describe "increment_counter" do
    context "counter equals 9" do
        it "calls tie_game?" do
            game.instance_variable_set(:@counter, 9)
            allow(game).to receive(:increment_counter)
            #expect(STDOUT).to receive(:puts).with("The game was a tie. Nicely played #{@player1} & #{@player2}!")
            expect(game).to receive(:tie_game?)
        end
    end
    context "counter is less than 9" do
        it "does not call tie_game?" do
            game.instance_variable_set(:@counter, 4)
            game.increment_counter
            expect(game).not_to receive(:tie_game?)  
        end
    end
end

这是一个有趣的问题。我的方法是猴子修补类,重新定义方法
tie\u game?
,这会产生一些可以通过测试检测到的副作用

因为我看不到你的类名,我们就叫它
Foo

首先,创建一个模块,比如说
TrackMethods

module TrackMethods
  # A global variable that stores how many times a method is called.
  $method_calls = Hash.new(0)

  def self.[](*method_names)
    Module.new do
      method_names.each do |name|
        define_method name do |*args, &block|
          $method_calls[name] += 1
          super(*args, &block)
        end
      end
    end
  end
end
然后在spec_helper.rb中

之后,在你的测试中,你可以

expect($method_calls[:tie_game?]).to be > 0

RSpec mock可以为您这样做

describe TicTacToe do
  let(:game) { TicTacToe.new }

  context "after fewer than 9 moves" do
    it "does not call tie_game?" do
      expect(game).not_to receive(:tie_game?)
      8.times { game.increment_counter }
    end
  end

  context "after 9 moves" do
    it "calls tie_game?" do
      expect(game).to receive(:tie_game?)
      9.times { game.increment_counter }
    end
  end
end
有关更多详细信息,请参阅


顺便说一句,平局?可能后面不应该有问号。平局?建议它正在检查游戏是否平局。

感谢您的回复,我刚刚对我的OPI进行了编辑,在我发布答案后,我看到了您的编辑。它不适用于您的原因是,在设置期望值之后,您从未真正调用代码。在测试是否发送和接收消息时,您必须颠倒期望/运行顺序。好的。非常感谢您的帮助,这肯定更有意义。非常感谢您的帮助,我可以因此删除很多代码。请注意,如果没有双倍,您不能使用
have\u received
。您必须测试
receive
,如本例所示。
describe TicTacToe do
  let(:game) { TicTacToe.new }

  context "after fewer than 9 moves" do
    it "does not call tie_game?" do
      expect(game).not_to receive(:tie_game?)
      8.times { game.increment_counter }
    end
  end

  context "after 9 moves" do
    it "calls tie_game?" do
      expect(game).to receive(:tie_game?)
      9.times { game.increment_counter }
    end
  end
end