Should Matcher에서 AttributeDoesNotExistError는 어떤 에러인가요...?


rspec과 factory-girl, shoulda-matcher을 이용해서 model spec를 작성하고있는데요.

shoulda-matcher에서 제공해주는 validate_presence_of를 이용해서 필드에 empty나 false가 들어 갈 수 없다는 spec를 작성해보고있는데요.

AttributeDoesNotExistError가 납니다...

아마 제가 shoulda-matcher 설정이나 설치를 잘못한것같은데, 어느부분을 봐야할지 몰라서요...

Gemfile

source 'https://rubygems.org'
ruby '2.3.0'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.6'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'

# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
gem 'pry'
gem 'pg', '~> 0.18.4'
gem 'figaro', '~> 1.1.1'
gem 'pry-rails'

# Use Unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :test do
  gem 'database_cleaner', '~> 1.5.1'
  gem 'shoulda-matchers', '~> 3.1.1'
end

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'
  gem 'rspec-rails', '~> 3.4.2'
  gem 'guard', '~> 2.13.0'
  gem 'guard-rspec', '~> 4.6.5'
  gem 'factory_girl_rails', '~> 4.7.0'
  gem 'faker', '~> 1.6.3'
end

group :development do
  gem 'web-console', '~> 2.0'

  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'annotate'
end

spec/spec_helper.rb

require 'database_cleaner'

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
    expectations.syntax = :expect
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
end

spec/rails_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'shoulda/matchers'

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true

  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
end

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

spec/factories/content.rb

# == Schema Information
#
# Table name: contents
#
#  id         :integer          not null, primary key
#  txt        :text
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

FactoryGirl.define do
  factory :content do
    txt { Faker::Lorem.paragraph }
  end
end

app/model/content.rb

# == Schema Information
#
# Table name: contents
#
#  id         :integer          not null, primary key
#  txt        :text
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Content < ActiveRecord::Base
  validates :txt, presence: true
end

Content 모델은 정상적으로 생성되어있습니다.

$ rails c
Running via Spring preloader in process 8237
Loading development environment (Rails 4.2.6)
[1] pry(main)> Content.create(txt: Faker::Lorem.paragraph)
   (0.2ms)  BEGIN
  SQL (2.1ms)  INSERT INTO "contents" ("txt", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["txt", "Amet temporibus nobis deserunt adipisci. Eligendi eveniet quo cumque voluptas ut quibusdam autem. Recusandae tempore consectetur qui veniam est hic voluptatem. Aliquam maxime et accusantium nostrum ad. Earum molestiae amet modi cupiditate id ut et."], ["created_at", "2016-04-11 02:08:09.637109"], ["updated_at", "2016-04-11 02:08:09.637109"]]
   (6.3ms)  COMMIT
=> #<Content:0x007fb828712d60
 id: 1,
 txt:
  "Amet temporibus nobis deserunt adipisci. Eligendi eveniet quo cumque voluptas ut quibusdam autem. Recusandae tempore consectetur qui veniam est hic voluptatem. Aliquam maxime et accusantium nostrum ad. Earum molestiae amet modi cupiditate id ut et.",
 created_at: Mon, 11 Apr 2016 11:08:09 KST +09:00,
 updated_at: Mon, 11 Apr 2016 11:08:09 KST +09:00>
[2] pry(main)> Content.last
  Content Load (0.4ms)  SELECT  "contents".* FROM "contents"  ORDER BY "contents"."id" DESC LIMIT 1
=> #<Content:0x007fb822044700
 id: 1,
 txt:
  "Amet temporibus nobis deserunt adipisci. Eligendi eveniet quo cumque voluptas ut quibusdam autem. Recusandae tempore consectetur qui veniam est hic voluptatem. Aliquam maxime et accusantium nostrum ad. Earum molestiae amet modi cupiditate id ut et.",
 created_at: Mon, 11 Apr 2016 11:08:09 KST +09:00,
 updated_at: Mon, 11 Apr 2016 11:08:09 KST +09:00>
[3] pry(main)>

spec/models/content_spec.rb

# == Schema Information
#
# Table name: contents
#
#  id         :integer          not null, primary key
#  txt        :text
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

require 'rails_helper'

describe Content do
  let(:content) { create(:content) }
  it 'is valid' do
    expect(build(:content)).to be_valid
  end

  it { expect(:content).to validate_length_of(:txt).is_at_least(100) }
end

rspec 실행

$ bundle exec rspec
.F

Failures:

  1) Content should validate that :txt cannot be empty/falsy
     Failure/Error: it { expect(:content).to validate_presence_of :txt }

     Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeDoesNotExistError:
       The matcher attempted to set :txt on the Symbol to nil, but that
       attribute does not exist.
     # ./spec/models/content_spec.rb:19:in `block (2 levels) in <top (required)>'

Finished in 0.29974 seconds (files took 1.49 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/models/content_spec.rb:19 # Content should validate that :txt cannot be empty/falsy

$

아무리 봐도 뭐가 문제인지 모르겠네요... ㅠㅠ

  • 2016년 04월 11일에 작성됨

조회수 207


1 답변


좋아요
3
싫어요
채택취소하기

Problem

it { expect(:content).to validate_length_of(:txt).is_at_least(100) }

expect:content 심볼을 넘겨서 그런거 같습니다.

Solution

it { expect(content).to validate_length_of(:txt).is_at_least(100) }

위와 같이 let으로 정의하신 content 변수를 넣으시거나, 또는

it { should validate_length_of(:txt).is_at_least(100) }

or

it { is_expected.to validate_length_of(:txt).is_at_least(100) }

이렇게 shoulda-matchers 에서 제공하는 shorthand method를 사용하시면 될 거 같습니다.


  • 헉 감사합니다...! 바로 해결되었네요.. 이런걸 발견 못하고.. ㅠㅠ    root   2016.4.11 12:28     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close