0

我正在开发的游戏中有以下方法:

  def search
    if rand(5) == 0
      weapon = Weapon.offset(rand(Weapon.count)).first
      users_weapon = UsersWeapon.create(user_id: self.id, weapon_id: weapon.id, ammo: weapon.max_ammo)
      self.users_weapons << users_weapon
      { :success => 'true', :weapon => users_weapon }
    else
      { :success => 'false' }
    end
  end

如你所见,我有两个rand's 。
现在,当我尝试使用 rspec 对其进行测试时,我想测试以下内容:

context 'when searches location' do
  subject(:user) { FactoryGirl.create :User }
  before { FactoryGirl.create :knife }
  before { FactoryGirl.create :pistol }

  context 'when finds knife' do
    before { srand(2) }
    it { user.search[:weapon].weapon.name.should == 'Knife' }
  end

  context 'when finds pistol' do
    before { srand(3) }
    it { p user.search[:weapon][:name].should == 'Pistol' }
  end

无论我在srand这里传递什么,它只能以以下两种方式之一起作用:
a)返回Pistol

b)返回 nil。

我想rand独立地存根这些 s。我不想weapon在每种情况下只播种一个,因为我想实际测试随机武器选择。我该如何执行?

4

2 回答 2

2

为您的方法使用意图揭示名称,然后模拟该方法而不是 rand

def search
  if rand(5) == 0
    weapon = Weapon.find_random
    # ...

class Weapon
  # ...
  def self.find_random
    self.offset(rand(self.count)).first

现在您可以轻松地模拟Weapon.find_random

如果需要,稍后可以轻松更改您的实现

class Weapon
  # ...
  def self.find_random
    # postgres
    self.order("RANDOM()").limit(1).first
    # mysql
    self.order("RAND()").limit(1).first        
于 2013-06-30T15:48:19.717 回答
0

几乎所有rand()的都是伪随机生成器,它们的随机性取决于你启动它们的种子,停止用相同的数字播种,而不是使用像 time( srand(gettime())) 这样的东西或者每次都会改变的东西。

PS:gettime()应该返回一个int,你必须为Ruby的正常时间函数返回的包装器将其转换为int

于 2013-06-30T14:02:17.420 回答