0

我有这个代码:

def self.generate_random_uniq_code
  code = sprintf("%06d", SecureRandom.random_number(999999))
  code = self.generate_random_uniq_code if self.where(code: code).count > 0
  code
end

目标是为新寄存器创建随机代码,该代码不能存在于我正在尝试以这种方式测试的寄存器中,但是当我模拟 SecureRandom 它总是返回相同的值:

it "code is unique" do
  old_code = Code.new
  old_code.code = 111111
  new_code = Code.new
  expect(SecureRandom).to receive(:random_number) {old_code.code}
  new_code.code = Code.generate_random_uniq_code
  expect(new_code.code).to_not eq old_code.code
end

我试图找出是否有办法启用和禁用模拟行为,但我找不到它,我不确定我是否以正确的方式进行测试,代码对我来说似乎无法正常工作。欢迎任何帮助,谢谢!

4

1 回答 1

3

TL;博士

通常,除非您实际上是在测试您编写的PRNG ,否则您可能正在测试错误的行为。考虑一下您实际尝试测试的行为,并检查您的替代方案。此外,一个六位数的数字实际上并没有足够的密钥空间来确保大多数用途的真正随机性,因此您可能需要考虑更健壮的东西。

一些替代品

应该始终测试行为,而不是执行。以下是一些可供考虑的替代方案:

  1. 使用UUID而不是六位数字。UUID 在统计上比您当前的解决方案更不可能遇到冲突。
  2. 通过调整架构在您的数据库列中强制执行唯一性。
  3. 在模型中使用Rails 唯一性验证器
  4. 使用FactoryGirl 序列或 lambda 为您的测试返回值。

修复您的规格

如果你真的坚持要测试这段代码,你至少应该使用正确的期望。例如:

# This won't do anything useful, if it even runs.
expect(new_code.code).to_not  old_code.code

相反,您应该检查是否相等,如下所示:

old_code = 111111
new_code = Code.generate_random_uniq_code
new_code.should_not eq old_code

您的代码可能会以其他方式被破坏(例如,您的方法中的代码变量似乎不是实例或类变量)所以我不能保证上述内容会起作用,但它至少应该指出您正确方向。

于 2013-08-23T19:06:24.917 回答