Rspec тест для уникальности атрибута объекта с неопределенным методом 'valid?' для ноля:NilClass

У меня есть объект с именем "Благотворительность", и я хочу убедиться, что у каждой благотворительной организации есть уникальное имя, к сожалению, я получаю следующий неудачный тест, подозреваю, что это проблема с моими фабриками:

Failures
     1) Charity name is already taken
       Failure/Error: it { @charity_with_same_name.should_not be_valid }
       NoMethodError:
         undefined method 'valid?' for nil:NilClass
       ...

Благотворительный объект принадлежит_объекту пользователя. Вот благотворительность.rb:

class Charity < ActiveRecord::Base
  attr_accessible :name, :description, :summary
  belongs_to :user

  validates :name, presence: true, uniqueness: { case_sensitive: false }, length: { maximum: 40 }
  validates :summary, presence: true, length: { maximum: 140 }
  validates :description, presence: true
  validates :user_id, presence: true

  default_scope order: 'charities.created_at DESC'
end

Вот соответствующие части charity_spec.rb:

require 'spec_helper'

describe Charity do

  let(:user) { FactoryGirl.create(:user) }
  #before { @charity = user.charities.build(summary: "Lorem ipsum") }
  before { @charity = user.charities.build(FactoryGirl.attributes_for(:charity)) }
  # this makes sure that all the attributes for charity are set, whereas
  #the previous code only sets the "summary" attribute

  subject { @charity }
  ...
  describe "name is already taken" do
    before do
      charity_with_same_name = @charity.dup
      charity_with_same_name.name = @charity.name.upcase
      charity_with_same_name.save
    end

    it { @charity_with_same_name.should_not be_valid }
  end
  ...

Вот этот файл factory.rb:

FactoryGirl.define do
  factory :user do
    sequence(:name)  { |n| "Person #{n}" }
    sequence(:email) { |n| "person_#{n}@example.com" }   
    password "foobar"
    password_confirmation "foobar"
    ...

    factory :charity do
      sequence(:name)        { |n| "charity #{n}" }
      sequence(:summary)     { |n| "summary #{n}" }
      sequence(:description) { |n| "description #{n}" }
    end
end

Что я сделал не так?

1 ответ

Решение

Ты можешь сделать charity_with_same_name переменная экземпляра в вашем блоке before (изменить charity_with_same_name в @charity_with_same_name) и изменить it { @charity_with_same_name.should_not be_valid } в specify { @charity_with_same_name.should_not be_valid } чтобы это прошло.

Проблема в том, что @charity_with_same_name не существует, потому что вы не инициализировали его. Вы только настроили charity_with_same_name, Кроме того, из-за subject { @charity }, it относится к @charity, так it { @charity_with_same_name.should_not be_valid } здесь не имеет смысла.

РЕДАКТИРОВАТЬ: В дополнение к вышеупомянутому, вам нужно будет добавить строку @charity.save в before блок (прямо перед линией charity_with_same_name = @charity.dup). Это необходимо, потому что ваша дублированная запись пройдет проверку (когда она не должна), несмотря на то, что она имеет то же имя, что и @charity так как @charity еще не был сохранен в базе данных. Как только благотворительность будет сохранена, проверочный тест проверит базу данных и увидит, что имя уже занято.

Другие вопросы по тегам