Simple Rspec test failure - ruby-on-rails

I have the following model:
module CgCart
class ShippingInfo < ActiveRecord::Base
set_table_name 'cg_cart.shipping_infos'
has_many :order, :class_name => "CgCart::Order"
accept_nested_attributes_for :orders, :allow_destroy => true
validates_presence_of :name, :street, :city, :country, :zip, :state
def to_s
retval = <<-formatted_addr
#{self.name}
#{self.street}
#{self.city} #{self.state} #{self.zip}
#{self.country}
formatted_addr
retval.upcase
end
end
end # module
I am writing a spec test. It goes like this:
require File.dirname(__FILE__) + '/../../spec_helper'
describe CgCart::ShippingInfo do
context "when first created" do
it "should be empty" do
#shipping_info = CgCart::ShippingInfo.new
#shipping_info.should be_empty
end
end
end
When I run the spec test I get the following error:
1)
NoMethodError in 'CgCart::ShippingInfo when first created should be empty'
undefined method `be_empty' for #<Spec::Matchers::PositiveOperatorMatcher:0x105f165c0>
./spec/models/cg_cart/shipping_info_spec.rb:6:
Finished in 0.015 seconds
1 example, 1 failure
This seems like it should very straight forward. Any ideas on why this test fails?

I was trying to use empty where I should have been using nil.
#shipping_info.should be_nil

Related

Rails minitest, why is my article model invalid?

I am starting to get into testing with minitest in Rails. Currently my first test to see if my model is valid is returning false. The error message itself is also very generic Expected false to be truthy. I have tested everything else and all of those tests work fine. Does anybody know what could be causing this?
article_test.rb
require 'test_helper'
class ArticleTest < ActiveSupport::TestCase
def setup
#article = Article.new(title:"Avengers Endgame", body:"I am inevitable")
end
test "article should be valid" do
assert #article.valid?
end
test "title should be present" do
#article.title = " "
assert_not #article.valid?
end
test "body should not be too short" do
#article.body = "aa"
assert_not #article.valid?
end
end
article.rb
class Article < ApplicationRecord
include Visible
belongs_to :user
has_many :comments, dependent: :destroy
has_rich_text :body
validates :title, presence: true
validates :body, presence: true, length: { minimum: 10 }
end
The main problem here is that you're using a poor method for testing your validations.
assert #article.valid? and assert_not #article.valid? does not actually tell you anything at all about the object under test. When the test fails you're none the wiser about why it actually failed and if the failure is actually even connected to what you're proportedly testing. At best it serves as a sort of litmus test that your test setup is correct.
Instead of this "carpet bombing" approach test each validation on its own:
class ArticleTest < ActiveSupport::TestCas
test "title should be present" do
article = Article.new(title: '')
article.valid?
assert_includes build_article.errors[:title], "can’t be blank"
end
test "body should not be too short" do
article = Article.new(body: 'aa')
article.valid?
assert_includes article.errors[:body], "is too short"
end
end
Testing all the validations at once (creating a record with valid input) will be covered by your integration and system tests anyways.
You have belongs_to :user, which expects the #article to have a user_id compulsorily to be present, before it can be saved.
If user_id is optional during creation, change this:
belongs_to :user
to
belongs_to :user, optional: true

error unit test: underfined assert_not

i have two error when i run rake test:
1)Error
test_should_require_a_following_id(RelationTest)
NoMethodError:underfined method 'assert_not' for #<RelationTest:0x3dd0058>
2)Error
test_should_require_a_follower_id(RelationTest)
NoMethodError:underfined method 'assert_not' for #<RelationTest:0x3c1d700>
this is my relation_test.rb
require 'test_helper'
class RelationTest < ActiveSupport::TestCase
def setup
#relation = Relation.new(follower_id: 9, following_id: 10)
end
test "should be valid" do
assert #relation.valid?
end
test "should require a follower_id" do
#relation.follower_id = nil
assert_not #relation.valid?
end
test "should require a following_id" do
#relation.following_id = nil
assert_not #relation.valid?
end
end
my relation model
class Relation < ActiveRecord::Base
attr_accessible :following_id, :follower_id
belongs_to :follower, :class_name => "User"
belongs_to :following, :class_name => "User"
validates :follower_id, presence: true
validates :following_id, presence: true
end
What can i do to fix that, please help me!
I think the problem is my rail vesion(3.2.19), but assert #relation.valid?still work??
assert_not has been added in rails 4.0.2. You need to do this instead:
assert !#relation.valid?

Testing ActiveRecord:Observer using RSpec

I have a model class as follows:
class DataInfo < ActiveRecord::Base
STATUS = {:UNAPPROVED => 1, :APPROVED => 2, :PROCESSED => 3 }
attr_accessible :id, :owner, :status
validates :status, :inclusion => {:in => STATUS.values}
end
I have written a observer as follows:
class StatusObserver < ActiveRecord::Observer
def after_save(datainfo)
if datainfo.status.eql? "APPROVED"
DataInfoWorker.perform_async datainfo.id
end
end
end
How do I test the observer using RSpec? Do I necessarily have to use "No Peeping Toms" plugin? I mainly want test after_save part of it?
You should be able to do something like this using rspec-3 syntax:
describe DataInfo do
describe 'after save when status is APPROVED' do
let(:data_info) { DataInfo.new(status: :APPROVED) }
before do
data_info.save!
end
it 'queues DataInfoWorker' do
expect(DataInfoWorker.jobs.size).to eq 1
end
end
end
Updated to test that a Sidekiq job is queued. Make sure that the rspec-sidekiq gem is added to your Gemfile.

Need help understanding why unit test for method is not working

I'm trying hard to cover all of my model's methods, associations and validation in my unit tests and so far it's going great. I've subscribed to TreeHouse and watched Ruby Foundations - Testing religiously.
I stumbled last night on this error while testing a method for my Provider.rb model:
class Provider < ActiveRecord::Base
attr_accessible :description, :name
validates :name, :presence => true
validates :description, :presence => true
validates :name, :length => { :minimum => 6, :maximum => 100 }
validates :description, :length => { :minimum => 6, :maximum => 100 }
has_many :courses
resourcify
def unique_locations
Location.joins(sessions: :course).where(courses: { provider_id: self.id }).uniq.pluck('locations.name')
end
end
My unit test for the unique_locations method is the following:
test 'should return a list of unique locations' do
provider = FactoryGirl.build(:provider)
assert_equal provider.unique_locations, ["location_1", "location_2"]
end
I get the following error after running my tests:
<[]> expected but was
<["location_1", "location_2"]>.
My factories are quite simple:
FactoryGirl.define do
factory :course do
name 'Snowboard 101'
description 'Snowboard course'
association :provider, factory: :provider
end
end
FactoryGirl.define do
factory :provider do
name 'The School of Hard Knocks'
description 'School description'
end
end
FactoryGirl.define do
factory :session_snowboard, class: Session do
name 'Winter Session'
description 'Snowboarding 101'
price 200
class_size 4
association :course, factory: :course
association :location, factory: :location_1
end
factory :session_ski, class: Session do
name 'skiing 101'
description 'Start in november'
price 100
class_size 4
association :course, factory: :course
association :location, factory: :location_2
end
end
FactoryGirl.define do
factory :location_1 do
name 'location_1'
end
factory :location_2 do
name 'location_2'
end
end
My unique_locations method works fine in my different environment. I just can't figure out why it's not returning the list of unique locations in test.
Any idea?
Thanks,
Francis
You are calling FactoryGirl.build(:provider) which only builds and doesn't save to the DB, so the unique_locations obviously wouldn't have the id to go by. Use create and it should fine.
So after much poking around with Factory_Girl I found the solution:
Here are my factories:
FactoryGirl.define do
factory :provider do
name 'McGill University'
description 'McGill is one of the best universities in the world.'
after(:create) {|provider| create_list(:course, 2, provider: provider) }
end
end
FactoryGirl.define do
factory :course do
name 'Snowboard 101'
description 'Snowboard course'
provider
after(:create) {|course| create_list(:session, 2, course: course) }
end
end
FactoryGirl.define do
factory :session do
name 'Winter Session'
description 'Snowboarding 101'
price 150
class_size 4
course
location
end
end
FactoryGirl.define do
factory :location do |l|
l.sequence(:name) { |n| "location_#{n}"}
end
end
I've also updated my test:
test 'should return a list of unique locations' do
provider = create(:provider)
assert_equal provider.unique_locations, %w[location_1 location_2 location_3 location_4]
end
This successfully creates 4 different locations.

validates_associated not honoring :if

I'm totally blocked on this.
See this code:
# user.rb
class User < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
validates_associated :address, :if => Proc.new {|u| u.addressable? }
end
# address.rb
class Address < ActiveRecord::Base
belongs_to :user
validates_presence_of :address_text
end
# user_test.rb
require File.dirname(__FILE__) + '/../test_helper'
class UserTest < ActiveSupport::TestCase
setup { }
test "address validation is not ran w update attributes and anaf" do
#user = User.create!
#user.build_address
assert_nothing_raised do
#user.update_attributes!(:addressable => false, :address_attributes => {:address => "test"})
end
end
test "address validation w update_attributes and anaf" do
#user = User.create!
#user.build_address
#user.save
assert_raise ActiveRecord::RecordInvalid do
#user.update_attributes!(:addressable => true, :address_attributes => {:address => "test"})
end
end
end
The first test will fail.
The user model validates an associated address model, but is only supposed to do it if a flag is true. In practice it does it all the time.
What is going on?
Actually I ran into further problems with my (more complicated) real world scenario that were only solved by doing the equivalent of:
def validate_associated_records_for_address
self.addressable? ? validate_single_association(User.reflect_on_association(:address)) : nil
end
This adapts anaf's compulsory validations to only run under the condition we want (addressable? is true).
The validates_associated...:if is not necessary now.

Resources