Ruby on rails 如何测试优惠券/促销代码的唯一性?
我有一个型号Ruby on rails 如何测试优惠券/促销代码的唯一性?,ruby-on-rails,rspec,rspec2,rspec-rails,Ruby On Rails,Rspec,Rspec2,Rspec Rails,我有一个型号PromoCode,它有一个。generate方法,该方法调用.generate,该方法使用SecureRandom.hex(5)生成字符串并将其保存到数据库: class PromoCode < ActiveRecord::Base class << self def generate SecureRandom.hex 5 end def generate! return create! code: gene
PromoCode
,它有一个。generate
方法,该方法调用.generate
,该方法使用SecureRandom.hex(5)
生成字符串并将其保存到数据库:
class PromoCode < ActiveRecord::Base
class << self
def generate
SecureRandom.hex 5
end
def generate!
return create! code: generate
end
end
end
感谢您的指导。如果您将promocode保存在数据库中,您将在uniq promocode的模型中添加验证。因此,您也可以在rspec中测试相同的功能 像这样,
it { should validate_uniqueness_of(:promocode) }
还有类似的事情:创建一个
PromoCode
,保存结果,然后尝试使用前一个PromoCode
对象的code
创建一个新的PromoCode
:
it "should reject duplicate promocode" do
@promo = PromoCode.generate!
duplicate_promo = PromoCode.new(:code => @promo.code)
duplicate_promo.should_not be_valid
end
此外,这是车型级别,我假设您在数据库中有一个密钥,可以将您从比赛条件中解救出来……此答案基于您的评论: 我需要确保这一点!生成代码-无论发生什么, 直到生成唯一的代码 我觉得你可能很难正确地测试这个。使用不确定循环的单元测试“无论发生什么”情况都可能是一个棘手的问题 我不知道该怎么做,因为我不能真正去掉.generate方法来返回固定值(因为那样它就会陷入无限循环) 一个可能考虑的是,如果不是做一个或另一个,你都试过了吗?(也就是说,找到一种方法,让它在某些情况下返回一个固定的数字,并最终触发实际的随机数。实例变量计数器可能会有所帮助;将它设置为随机数,然后倒计时,当它大于零时返回固定数,或者沿着这些线返回)。尽管如此,这仍然不是一个完美的测试,甚至不是一个非常好的测试
也许值得更多地研究生成类似字符串的方法,这些字符串很可能是唯一的,并且有一些数学证明。我也不是说这是最实际的想法,但如果您真的需要证明(正如您尝试测试时所做的),它可能是更可能的解决方案。Rspec的
和_return
方法允许您指定将循环的多个返回值
比如你可以写
PromoCode.stub(:generate).and_return('badcode1', 'badcode2', 'goodcode')
这将导致生成的第一个调用返回'badcode1',第二个'badcode2'等。。。然后,您可以检查返回的promocode是否使用正确的代码创建
如果您想证明竞态条件,那么您需要一个数据库唯一性约束,因此您的代码实际上可能需要这样做
def generate!
create!(...)
rescue ActiveRecord::RecordNotUnique
retry
end
在您的规范中,您将创建存根!方法第一次提升,但第二次返回值我需要确保
生成代码>生成一个代码-不管怎样,直到生成一个唯一的代码。从我的观点来看,这将在另一个测试中。在这里,您只是测试它是否拒绝重复的代码。好的。但这就是我一开始想要写的测试;)哇,我不知道。而且它的实现甚至比我想象的还要优雅(使用循环和按代码查找)。谢谢!
def generate!
create!(...)
rescue ActiveRecord::RecordNotUnique
retry
end