1

以下に示す、投票モデル用の次の Rspec テストがあります。これには、独自のコンテンツに投票できないことを保証するカスタム検証が含まれています。仕様内の他のテストがパスするのに、なぜこれらのテストのうち 2 つだけが nilclass エラーで失敗するのか、私は困惑しています。

@vote は nil でなければなりませんが、他のテストが同じエラーで失敗しないのはなぜですか?

投票.rb

validates :ensure_not_author

def ensure_not_author 
    votable = self.votable_type.downcase
    errors.add(:user_id, "You can't vote on your own content.") if self.votable.user_id == self.user_id
  end

工場

factory :answer do
    user_id :user
    question_id :question
    body "you need to change your grip"
    votes_count 0
    correct false
  end

  factory :vote do
    user_id :user
    votable_id :answer
    votable_type "Answer"
    value 1
    points 5
  end

factory :user do |u|
    u.sequence(:email) {|n| "test#{n}@hotmail.com"}
    u.sequence(:username) {|n| "tester#{n}" }
    u.password "password"
    u.password_confirmation "password" 
    u.remember_me true
    u.reputation 200
  end

投票_spec.rb

require "spec_helper"

describe Vote do
  before(:each) do
    @user2 = FactoryGirl.create(:user)
    @user = FactoryGirl.create(:user)
    @answer = FactoryGirl.create(:answer, user_id: @user)
    @vote = Vote.create(user_id: @user2.id, value: 1, points: 5, votable_id: @answer.id, votable_type: "Answer")
  end

  subject { @vote }

  it { should respond_to(:user_id) }
  it { should respond_to(:votable_id) }
  it { should respond_to(:votable_type) }
  it { should respond_to(:value) }
  it { should respond_to(:points) }

   describe 'value' do
     before { @vote.value = nil }
     it { should_not be_valid }
   end

   describe "user_id" do
      before { @vote.user_id = nil }
       it { should_not be_valid }
     end

   describe "votable_id" do
     before { @vote.votable_id = nil }
     it { should_not be_valid }
   end

   describe "votable type" do
      before { @vote.votable_type = nil }
      it { should_not be_valid }
   end

   describe "vote value" do
      before { @vote.value = 5 }
      it { should_not be_valid }
   end
end

失敗:

1) Vote votable_id 
     Failure/Error: it { should_not be_valid }
     NoMethodError:
       undefined method `user_id' for nil:NilClass
     # ./app/models/vote.rb:17:in `ensure_not_author'
     # ./spec/models/vote_spec.rb:25:in `block (3 levels) in <top (required)>'

  2) Vote votable type 
     Failure/Error: it { should_not be_valid }
     NoMethodError:
       undefined method `downcase' for nil:NilClass
     # ./app/models/vote.rb:16:in `ensure_not_author'
     # ./spec/models/vote_spec.rb:35:in `block (3 levels) in <top (required)>'
4

1 に答える 1

2

あなたのバリデーターensure_not_authorは依存Vote#votable_typeし、Vote#votableうまく機能します。の有効性をテストすると@vote、このバリデーターがテストされます。

ただし、"votable_id"テストケースでは、に設定votable_idしましたnil。後で@voteで の有効性をテストするとshould_not be_validensure_not_authorが呼び出されて失敗します。self.votable.user_idこれは、ActiveRecord が wi​​th に対してクエリを実行するためVotableですvotable_id

同様に、 に設定したため、"votable type"テスト ケースは で失敗しました。self.votable_type.downcasevotable_typenil

メッセージを送信する前に、バリデーターで属性が使用可能かどうかを確認する必要があります。または、前にチェックする他のバリデータを作成しますensure_not_author

于 2013-06-20T13:48:14.050 に答える