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;DR

一般に、作成したPRNGを実際にテストしていない限り、間違った動作をテストしている可能性があります。実際にテストしようとしている動作を検討し、代替案を検討してください。さらに、6 桁の数値では、ほとんどの目的で真のランダム性を保証するのに十分なキー スペースがないため、より堅牢なものを検討することをお勧めします。

いくつかの代替案

実装ではなく、常に動作をテストする必要があります。考慮すべきいくつかの代替案を次に示します。

  1. 6 桁の数字の代わりにUUIDを使用します。UUID は、統計的に、現在のソリューションよりも衝突に遭遇する可能性が低くなります。
  2. スキーマを調整して、データベース列の一意性を強化します。
  3. モデルでRails 一意性バリデーターを使用する。
  4. FactoryGirl シーケンスまたはラムダを使用して、テストの値を返します。

仕様を修正する

このコードをどうしてもテストしたいのであれば、少なくとも正しい期待値を使用する必要があります。例えば:

# 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 に答える