【问题标题】:RSpec mock fails with "undefined method `-' for nil:NilClass"RSpec 模拟因“nil:NilClass 的未定义方法 `-'”而失败
【发布时间】:2010-12-22 02:25:53
【问题描述】:

我想用 RSpec 测试一个简单的方法。我想确保 applyplayer.capacity 减一。为此,我模拟了一个播放器对象并正在测试它是否接收到正确的消息。

代码

class DecreaseCapacity < Item
  def apply player
    player.capacity -= 1
  end
end

测试

describe DecreaseCapacity, "#apply" do
  it "should decrease capacity by one" do
    player = double()
    player.should_receive(:capacity)   # reads the capacity
    player.should_receive(:capacity=)  # decrement by one
    subject.apply player
  end
end

失败信息

1) DecreaseCapacity#apply should decrease the player's capacity by one
   Failure/Error: subject.apply player
   undefined method `-' for nil:NilClass
   # ./item.rb:39:in `apply'
   # ./item_spec.rb:25

这里发生了什么?为什么player.capacity -= 1 试图在nil 上调用-

【问题讨论】:

    标签: ruby unit-testing rspec rspec2


    【解决方案1】:

    问题在于,当调用 capacity 时,您对播放器进行存根的方式将返回 nil。你需要像这样改变:

    player.should_receive(:capacity).and_return(0)
    player.should_receive(:capacity=).with(1)
    

    要了解原因,让我们分解代码中发生的情况。如果我们将-= 扩展为:

    player.capacity = player.capacity - 1
    

    使用你的存根播放器会变成这样:

    player.capacity = nil - 1
    

    这正是 RSpec 所抱怨的。

    现在,让我建议一种更好的方法来编写测试。您的测试只是反映您的实现,它不测试方法。我的意思是它不测试apply 方法是否将玩家的容量增加一——它测试apply 调用capacity 然后capacity=。您可能认为这是同一件事,但这只是因为您知道您是如何实现该方法的。

    这就是我编写测试的方式:

    it "increments a player's capacity" do
      player = Player.new # notice that I use a real Player
      player.capacity = 0
      subject.apply(player)
      player.capacity.should == 1
    end
    

    我使用真正的Player 对象而不是设置存根,因为我假设Player#capacity 的实现只是一个访问器,其中没有任何逻辑可以干扰我的测试。使用存根的风险在于,有时存根会变得比实际对象更复杂(在这种情况下,我会争辩),这意味着您的测试比实际代码更有可能出错。

    如果你想使用 RSpec 的完整表达能力,你也可以这样写测试:

    it "increments a player's capacity" do
      player = Player.new
      player.capacity = 0
      expect { subject.apply(player) }.to change { player.capacity }.to(1)
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-24
      • 2015-02-27
      • 2014-08-14
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 2019-12-29
      相关资源
      最近更新 更多