24

次の(簡略化された)Rails懸念があります。

module HasTerms
  extend ActiveSupport::Concern

  module ClassMethods
    def optional_agreement
      # Attributes
      #----------------------------------------------------------------------------
      attr_accessible :agrees_to_terms
    end

    def required_agreement
      # Attributes
      #----------------------------------------------------------------------------
      attr_accessible :agrees_to_terms

      # Validations
      #----------------------------------------------------------------------------
      validates :agrees_to_terms, :acceptance => true, :allow_nil => :false, :on => :create
    end
  end
end

RSpec でこのモジュールをテストする良い方法がわかりません。ダミー クラスを作成しただけでは、検証が機能していることを確認しようとすると、アクティブ レコード エラーが発生します。他の誰かがこの問題に直面しましたか?

4

5 に答える 5

7

このモジュールを含むクラスにテストを残すことで、モジュールを暗黙的にテストすることができます。または、ダミー クラスに他の必須モジュールを含めることもできます。たとえばvalidates、AR モデルのメソッドは によって提供されActiveModel::Validationsます。だから、あなたのテストのために:

class DummyClass
  include ActiveModel::Validations
  include HasTerms
end

モジュールで暗黙的に依存している依存関係に基づいて、他のモジュールを取り込む必要がある場合がありHasTermsます。

于 2013-05-09T02:29:47.707 に答える
7

私はこれに苦労していて、次の解決策を思いつきました。これは rossta のアイデアによく似ていますが、代わりに匿名クラスを使用します。

it 'validates terms' do
  dummy_class = Class.new do
    include ActiveModel::Validations
    include HasTerms

    attr_accessor :agrees_to_terms

    def self.model_name
      ActiveModel::Name.new(self, nil, "dummy")
    end
  end

  dummy = dummy_class.new
  dummy.should_not be_valid
end
于 2013-09-03T08:39:19.120 に答える
4

別の例を次に示します (Factorygirl の「create」メソッドと shared_examples_for を使用)

気になるスペック

#spec/support/concerns/commentable_spec
require 'spec_helper'
shared_examples_for 'commentable' do
  let (:model) { create ( described_class.to_s.underscore ) }
  let (:user) { create (:user) }

  it 'has comments' do
    expect { model.comments }.to_not raise_error
  end
  it 'comment method returns Comment object as association' do
    model.comment(user, "description")
    expect(model.comments.length).to eq(1)
  end
  it 'user can make multiple comments' do
    model.comment(user, "description")
    model.comment(user, "description")
    expect(model.comments.length).to eq(2)
  end
end

コメント可能な懸念

module Commentable
  extend ActiveSupport::Concern
  included do
    has_many :comments, as: :commentable
  end

  def comment(user, description)
    Comment.create(commentable_id: self.id,
                  commentable_type: self.class.name,
                  user_id: user.id,
                  description: description
                  )
  end

end

そして、restraunt_spec は次のようになります (私は Rspec の第一人者ではないので、私の仕様書の書き方が良いとは思いません。最も重要なことは冒頭にあります)。

require 'rails_helper'

RSpec.describe Restraunt, type: :model do
  it_behaves_like 'commentable'

  describe 'with valid data' do
    let (:restraunt) { create(:restraunt) }
    it 'has valid factory' do
      expect(restraunt).to be_valid
    end
    it 'has many comments' do
      expect { restraunt.comments }.to_not raise_error
    end
  end
  describe 'with invalid data' do
    it 'is invalid without a name' do
      restraunt = build(:restraunt, name: nil)
      restraunt.save
      expect(restraunt.errors[:name].length).to eq(1)
    end
    it 'is invalid without description' do
      restraunt = build(:restraunt, description: nil)
      restraunt.save
      expect(restraunt.errors[:description].length).to eq(1)
    end
    it 'is invalid without location' do
      restraunt = build(:restraunt, location: nil)
      restraunt.save
      expect(restraunt.errors[:location].length).to eq(1)
    end
    it 'does not allow duplicated name' do
      restraunt = create(:restraunt, name: 'test_name')
      restraunt2 = build(:restraunt, name: 'test_name')
      restraunt2.save
      expect(restraunt2.errors[:name].length).to eq(1)
    end
  end
end
于 2015-06-11T12:49:56.677 に答える
3

Aaron Kの優れた回答heredescribed_classに基づいて、RSpecが提供するメソッドをユビキタスにし、ファクトリを機能させるために使用できるいくつかの素晴らしいトリックがあります。これは、私が最近アプリケーション用に作成した共有例のスニペットです。

shared_examples 'token authenticatable' do
  describe '.find_by_authentication_token' do
    context 'valid token' do
      it 'finds correct user' do
        class_symbol = described_class.name.underscore
        item = create(class_symbol, :authentication_token)
        create(class_symbol, :authentication_token)

        item_found = described_class.find_by_authentication_token(
          item.authentication_token
        )

        expect(item_found).to eq item
      end
    end

    context 'nil token' do
      it 'returns nil' do
        class_symbol = described_class.name.underscore
        create(class_symbol)

        item_found = described_class.find_by_authentication_token(nil)

        expect(item_found).to be_nil
      end
    end
  end
end
于 2013-09-28T19:48:25.337 に答える