我正在开发的游戏中有以下方法:
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
现在,当我尝试使用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
OR
b)返回nil。
我想独立存根这些rand
。我不想在每个上下文中只种一weapon
因为我想实际测试随机武器选择。我怎么能表演呢?
答案 0 :(得分: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
答案 1 :(得分:0)
几乎所有rand()
都是伪随机生成器,它们的随机性取决于你启动它们的种子,停止播种相同的数字,而不是使用时间(srand(gettime())
)或每次都改变的东西。
PS:gettime()
应该返回一个int,你必须为Ruby做一个包装器,正常的时间函数返回它将它转换为int