Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何测试优惠券/促销代码的唯一性?_Ruby On Rails_Rspec_Rspec2_Rspec Rails - Fatal编程技术网

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