1

在开始之前,我使用带有 rspec、shouda-matchers 和 factorygirl 的 rails 来简化测试,所以如果这些库包含有助于解决以下问题的内容,请告诉我。

我正在设计我的控制器和模型,但不确定如何测试这种情况。

我有一个游戏模型,它可以包含一堆玩家。只有在游戏还没有开始的情况下才能移除玩家,所以我在我的游戏模型中添加了一个 remove_player 方法并对其进行了彻底的测试。

在我的播放器控制器中,我有调用 remove_player 方法的删除操作来实际完成工作,然后该操作导致重定向。

如何在不重新测试方法的情况下测试控制器实际上正在做它应该做的事情(调用 remove_player)?我可以测试进行重定向,但如果将来删除对 remove_player 的调用,这不会失败。

我知道 shoulda-matchers 有“should_validate_presence_of”之类的东西,这与这个测试背后的想法相同,但不适用于我自己的方法。

4

1 回答 1

1

昨晚我尝试了模拟和存根,它们完全符合我的要求。RSpec 的 mock很容易上手,并且包含在 rspec gem 中。

存根的基本思想是替换您用来测试另一个对象的真实对象。在我的问题示例中,我可以在测试玩家控制器时制作游戏模型的存根,并说 gamestub.remove_player 始终返回 true。在 RSpec 你可以这样做

@game = double("game") #a double is rspec's mock/stub object
@game.stub(:remove_player?).and_return(true)

模拟有点不同,因为它不仅是您正在模拟的对象的替代品,而且还是您的测试条件的一部分。你不仅可以说如果你的假对象被调用会返回什么,还可以说它应该被调用 n 次(否则测试将失败),以及你希望使用什么参数来调用它。在上面的例子中,我可以模拟一个游戏,并说 gamemock.remove_player 应该被调用一次并传入当前玩家并返回 true(如果我想测试如果测试失败会发生什么,则返回 false)。这是一个类似于我为玩家控制器所做的示例。

@game = double("game")
Game.should_receive(:find_by_id).with("123").and_return { @game }
@game.should_receive(:remove_player?).with(current_user).and_return(true)
delete :destroy, {:id => 123}
response.should do_whatever

模拟和存根非常相似。本文试图强调差异。在我看来,这基本上就是您使用它们的方式,因为模拟具有存根的所有功能,并且可以用作其中之一。这可能就是为什么 RSpec 将它们视为一种类型(双重)

于 2013-04-25T20:08:48.360 回答