2

私はメソッドを持つモデルPromoCodeを持っています。これは、使用して文字列を生成し、それをデータベースに保存します。.generate!.generateSecureRandom.hex(5)

class PromoCode < ActiveRecord::Base
  class << self
    def generate 
      SecureRandom.hex 5
    end

    def generate!
      return create! code: generate
    end
  end
end

ここで、生成された文字列の一意性をテストする仕様を書きたいと思います。この.generateメソッドは、存在しない PromoCode が生成されている限り呼び出す必要があります。

メソッドを実際にスタブ化して固定値を返すことができないため、これを行う方法がわかりません.generate(無限ループに陥ってしまうため)。

これは、これまでのモデルの合格仕様です。

describe PromoCode do
  describe ".generate" do
    it "should return a string with a length of 10" do
      code = PromoCode.generate
      code.should be_a String
      code.length.should eql 10
    end
  end

  describe ".generate!" do
    it "generates and returns a promocode" do
      expect {
        @promo = PromoCode.generate!
      }.to change { PromoCode.count }.from(0).to(1)

      @promo.code.should_not be_nil
      @promo.code.length.should eql 10
    end

    it "generates a uniq promocode" do
    end
  end
end

任意の指示をいただければ幸いです。

4

4 に答える 4

3

そして、次のようなものはどうでしょうか。を作成しPromoCode、結果を保存して、前のオブジェクトPromoCodeのを使用して新しいオブジェクトを作成してみてください。codePromoCode

it "should reject duplicate promocode" do
  @promo = PromoCode.generate!
  duplicate_promo = PromoCode.new(:code => @promo.code)
  duplicate_promo.should_not be_valid
end

また、これはモデルレベルです。データベースに、競合状態からあなたを救うキーがあると仮定しています...

于 2012-08-10T12:51:30.820 に答える
3

Rspec のand_returnメソッドを使用すると、循環する複数の戻り値を指定できます

たとえば、次のように書くことができます

PromoCode.stub(:generate).and_return('badcode1', 'badcode2', 'goodcode')

これにより、最初の呼び出しで「badcode1」、2 番目の「badcode2」などが返されます。返されたプロモーション コードが正しいコードで作成されたことを確認できます。

競合状態を証明したい場合は、データベースの一意性制約が必要になるため、コードは実際には

def generate!
   create!(...)
rescue ActiveRecord::RecordNotUnique
  retry
end

あなたの仕様では、作成をスタブします! 1 回目は発生させるが 2 回目は値を返すメソッド

于 2012-08-10T13:20:15.383 に答える
0

プロモコードをデータベースに保存すると、uniqプロモコードのモデルに検証が追加されます。したがって、rspecでも同じことをテストできます。

このような、

it { should validate_uniqueness_of(:promocode) }
于 2012-08-10T12:16:42.940 に答える
0

この回答はあなたのコメントに基づいています:

私はそれが生成されることを確認する必要があります! 一意のコードが生成されるまで、何があってもコードを生成します。

これを正しくテストするのに苦労するかもしれないと思います。「何があっても」不定ループを伴う状況での単体テストは、少しトリッキーなテーマになる可能性があります。

.generate メソッドを実際にスタブ化して固定値を返すことができないため、これを行う方法がわかりません (無限ループに陥ってしまうため)。

考慮すべき 1 つの可能性は、どちらか一方を実行する代わりに、両方を試した場合です。(つまり、特定の状況下で固定数を返すようにする方法を見つけ、最終的に実際の乱数をトリガーします。インスタンス変数カウンターが役立つ場合があります。乱数に設定し、カウントダウンし、ゼロより大きい場合は、固定数、またはそれらの線に沿った何か)。ただし、これはまだ完璧なテストのようには感じられません。

一意である可能性が高い同様の文字列を生成する手段をさらに検討し、それがそのようであることを数学的に証明することは価値があるかもしれません。これが最も実用的なアイデアだと言っているわけではありませんが、(テストでやろうとしているように)本当に証明する必要がある場合は、それがより可能性の高い解決策かもしれません.

于 2012-08-10T13:15:55.767 に答える