I'm writing a model spec using rspec, factory-girl, and shoulda-matcher.
Using validate_presence_of
provided by shoulda-matcher, we are writing a spec that an empty or false cannot be entered in the field.
AttributeDoesNotExistError is displayed..
Maybe I set up the shoulder or installed it wrong, but I didn't know which part to look at...
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 models are created successfully.
$ rails c
Running via Spring preloader in process 8237
Loading development environment (Rails 4.2.6)
[1] [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] [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] [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
Run rspec
$ bundle exec rspec
.F
Failures:
1) 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
$
I don't know what the problem is. ㅠ<
ruby-on-rails ruby shoulda-matcher rspec ruby-on-rails-4
Problem
it { expect(:content).to validate_length_of(:txt).is_at_least(100) }
I think it's because it passed the :content
symbol to aspect
.
Solution
it { expect(content).to validate_length_of(:txt).is_at_least(100) }
Enter the content
variable defined by let
as above, or
it { should validate_length_of(:txt).is_at_least(100) }
or
it { is_expected.to validate_length_of(:txt).is_at_least(100) }
Like this, you can use the short and method provided by shoulda-matchers
.
© 2024 OneMinuteCode. All rights reserved.