I have the following test code:
require 'spec_helper'
require 'matchers/be_valid_verbose'
describe User do
before do
#user = User.new(first_name: "First", last_name: "Last", email: "test#test.com", role: "admin",
password: "foobar12", password_confirmation: "foobar12")
end
subject ( #user )
specify { should be_valid_verbose }
describe "return value of authendicate method" do
before { #user.save }
let(:found_user) { User.find_by_email(#user.email) }
describe "with valid password" do
it { should == found_user.authenticate(#user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invlaid") }
it { should_not == user_for_invalid_password }
specify { user_for_invalid_password.should be_false }
end
end
end
I don't understand why: it { should be_valid } is gettig a totally empty user object. The same is happening when I try to find_by_email after just creating the user object in the before do statement.
Here's my test output
$ bundle exec rspec spec/models/user_trial_spec.rb
FF..
Failures:
1) User
Failure/Error: specify { should be_valid_verbose }
expected valid? to return true, got false:
Password digest can't be blank
First name can't be blank
Last name can't be blank
Role is not included in the list
Email can't be blank
Email is invalid
Password can't be blank
Password is too short (minimum is 8 characters)
Password confirmation can't be blank
# ./spec/models/user_trial_spec.rb:25:in `block (2 levels) in <top (required)>'
2) User return value of authendicate method with valid password
Failure/Error: it { should == found_user.authenticate(#user.password) }
expected: #<User id: 10, first_name: "First", last_name: "Last", email: "test#test.com", role: "admin", password_digest: "$2a$10$Z0c6zJNH4yu8IpYfNqEbKOmqEWK.euTFcYuwB/8UW9jk...", created_at: "2012-11-13 21:44:55", updated_at: "2012-11-13 21:44:55", remember_token: nil>
got: #<User id: nil, first_name: nil, last_name: nil, email: nil, role: nil, password_digest: nil, created_at: nil, updated_at: nil, remember_token: nil> (using ==)
Diff:
## -1,2 +1,2 ##
-#<User id: 10, first_name: "First", last_name: "Last", email: "test#test.com", role: "admin", password_digest: "$2a$10$Z0c6zJNH4yu8IpYfNqEbKOmqEWK.euTFcYuwB/8UW9jk...", created_at: "2012-11-13 21:44:55", updated_at: "2012-11-13 21:44:55", remember_token: nil>
+#<User id: nil, first_name: nil, last_name: nil, email: nil, role: nil, password_digest: nil, created_at: nil, updated_at: nil, remember_token: nil>
# ./spec/models/user_trial_spec.rb:32:in `block (4 levels) in <top (required)>'
Finished in 2.3 seconds
4 examples, 2 failures
Failed examples:
rspec ./spec/models/user_trial_spec.rb:25 # User
rspec ./spec/models/user_trial_spec.rb:32 # User return value of authendicate method with valid password
Randomized with seed 39450
Okay i just saw the problem. I was using
subject ( #user )
instead of the correct
subject { #user }
DOH!
Related
I've been getting intermittent errors while seeding with rails. I'm hoping someone can help provide some insight into the different types of the User class.
The error in full:
ActiveRecord::AssociationTypeMismatch: User(#35560) expected, got #<User id: "bedc7c4e-cdd2-4ea1-a7ee-4e6642467fba", email: "phil#email.domain", jti: "7376cf41-7f88-407d-8365-1e311d946b88", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:16:37.559974000 +0000", updated_at: "2023-02-08 08:16:37.559974000 +0000"> which is an instance of User(#22700)
The code which causes it:
user = User.new(
first_name: 'Phil',
last_name: '6',
email: 'phil#email.domain',
super_user: true,
password: 'test1234'
)
user.skip_confirmation!
user.save!
organisation = Organisation.find_by_name('Team')
Membership.create!(
user:,
organisation:,
verified: true,
verified_at: now,
organisation_admin: true,
shift_admin: true,
email: 'phil.6#group.com',
email_confirmed: true,
category: organisation.categories.find_by_name('Developer')
)
organisation = Organisation.find_by_name('Test Org')
membership = Membership.create!(
user:,
organisation:,
verified: true,
verified_at: now,
email: 'phil#testorg.com',
email_confirmed: true
)
If I pause execution before the error I can see that user == User.first is false despite User.first and user being these two lines, which are visually identical:
#<User id: "6ce62b08-cf4c-4bfa-878a-02a1ed889c69", email: "phil#email.domain", jti: "710948b6-5f4f-40ea-ab9f-df8e3b1219c3", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:17:06.024800000 +0000", updated_at: "2023-02-08 08:17:06.024800000 +0000">
#<User id: "6ce62b08-cf4c-4bfa-878a-02a1ed889c69", email: "phil#email.domain", jti: "710948b6-5f4f-40ea-ab9f-df8e3b1219c3", ios_device_token: nil, fcm_device_token: nil, first_name: "Phil", last_name: "6", phone_number: nil, date_of_birth: nil, super_user: true, created_at: "2023-02-08 08:17:06.024800000 +0000", updated_at: "2023-02-08 08:17:06.024800000 +0000">
It's the same thing if I compare user.class and User.first.class, they look the same but a comparison evaluates to false.
Am I doing something to mutate the local variable?
What you should be doing here is to create an assocation:
class User < ApplicationRecord
has_many :memberships
end
Then you create the memberships through that assocation instead:
user = User.create!(
first_name: 'Phil',
last_name: '6',
email: 'phil#email.domain',
super_user: true,
password: 'test1234',
confirmed_at: Time.current # the easy way to skip Devise::Confirmable
)
# make sure you use the bang method so that you're not just getting a nil
organisation = Organisation.find_by_name!('Test Org')
user.memberships.create!(
organisation: organisation,
verified: true,
verified_at: now,
organisation_admin: true,
shift_admin: true,
email: 'phil.6#group.com',
email_confirmed: true,
category: organisation.categories.find_by_name!('Developer')
)
I am trying to test the following controller action(Using Ruby on Rails, RSPEC, and FactoryGirl):
class ContactsController < ApplicationController
before_action :authenticate_user!
def index
#contacts = current_user.contacts
# #contacts = Contact.all
end
Here is my contacts_controller_spec.rb file:
require 'rails_helper'
describe ContactsController do
before do
#user = FactoryGirl.create(:user_with_contacts)
sign_in #user
end
describe "GET INDEX" do
it "assigns #contacts" do
expect(assigns(:contacts)).to eq(#user.contacts)
end
end
Failure/Error: expect(assigns(:contact)).to eq([contact])
expected: [#<Contact id: 295, first_name: "Loy", email: "leon#hegmannhintz.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Wyman", user_id: 343>]
got: #<Contact id: nil, first_name: nil, email: nil, phone_number: nil, created_at: nil, updated_at: nil, last_name: nil, user_id: nil>
And here is my users_spec.rb file:
FactoryGirl.define do
factory :user do
email { Faker::Internet.email }
password { "32423fdsfasf42" }
factory :user_with_contacts do
transient do
contacts_count 2
end
after(:create) do |user, evaluator|
create_list(:contact, evaluator.contacts_count, user: user)
end
end
end
end
Any Help please? I have been stuck on this for a long time.
If i call
puts #user.inspect
I get
#<User id: 340, email: "johnson_kaulke#brekke.com", encrypted_password: "$2a$04$Si5k6Q1eYERvhQITXKBoIOGEzPyK50E3IQ.yjRcqmDj...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42">
and
calling
puts #user.contacts.inspect
I get
#<ActiveRecord::Associations::CollectionProxy [#<Contact id: 289, first_name: "Fae", email: "ariane#johnston.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Spinka", user_id: 340>, #<Contact id: 290, first_name: "Marcellus", email: "chloe_deckow#buckridge.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Bashirian", user_id: 340>]>
Its just when i call the assigns(:contacts) that the problem happens!
I think you forgot to invoke the controller action. :)
Try adding get :index
it "assigns #contacts" do
get :index
expect(assigns(:contacts)).to eq(#user.contacts)
end
I can't figure out what I'm doing wrong in my model spec (user_spec.rb). I'm attempting to check that the authentication method works with a valid password, but something is going wrong in the User.find_by part of the spec I think since it returns nil. I've checked that it responds to :authenticate, :password, and :password_confirmation, which passes (I'll omit that in the code below for the sake of readability).
Here's the failure I'm getting when running the spec:
Failures:
1) User return value of authenticate method with valid password should eq #<User id: 136, fullname: "Sherwood Hickle", email: "jewell.brekke#stokes.net", created_at: "2013-11-06 23:04:35", updated_at: "2013-11-06 23:04:35", password_digest: "$2a$04$O5V2X9sZrl/u2T9W25c3Pu/PU6XaIvtZSIB39Efkid6a...">
Failure/Error: it { should eq found_user.authenticate(user.password) }
expected: #<User id: 136, fullname: "Sherwood Hickle", email: "jewell.brekke#stokes.net", created_at: "2013-11-06 23:04:35", updated_at: "2013-11-06 23:04:35", password_digest: "$2a$04$O5V2X9sZrl/u2T9W25c3Pu/PU6XaIvtZSIB39Efkid6a...">
got: #<User id: nil, fullname: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil>
(compared using ==)
Diff:
## -1,2 +1,2 ##
-#<User id: 136, fullname: "Sherwood Hickle", email: "jewell.brekke#stokes.net", created_at: "2013-11-06 23:04:35", updated_at: "2013-11-06 23:04:35", password_digest: "$2a$04$O5V2X9sZrl/u2T9W25c3Pu/PU6XaIvtZSIB39Efkid6a...">
+#<User id: nil, fullname: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil>
# ./spec/models/user_spec.rb:41:in `block (4 levels) in <top (required)>'
user_spec.rb:
require 'spec_helper'
describe User do
describe "return value of authenticate method" do
user = FactoryGirl.create(:user)
let(:found_user) { User.find_by(email: user.email) }
describe "with valid password" do
it { should eq found_user.authenticate(user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not eq user_for_invalid_password }
specify { expect(user_for_invalid_password).to be_false }
end
end
end
And I'm also using FactoryGirl to generate the username and email addresses but I don't think it has anything to do with the failure:
require 'faker'
FactoryGirl.define do
factory :user do |u|
u.fullname { Faker::Name.name }
u.email { Faker::Internet.email }
u.password { "foobar" }
u.password_confirmation { "foobar" }
end
end
The problem is the way the spec is set up. You're using an implicit subject which, for this spec, will be User.new. That's why you're seeing a User object with all nil attributes.
Your it clauses should read more like
it { found_user.authenticate(user.password).should eq user }
and
it { user_for_invalid_password.should be_nil }
which actually test the behavior.
UPDATE:
With the introduction in RSpec 3.x of expect syntax as the preferred syntax, this would now be:
it { expect(found_user.authenticate(user.password)).to eq user }
and
it { expect(user_for_invalid_password).to be_nil }
I am a bit of a freshman in rails, so please bear with me.
I get a routing error on my tests. The tests are as follwoing:
require 'spec_helper'
describe "ProducerPages" do
subject { page }
describe "profile page" do
#producer = Producer.create(name:"Example Producer",
email: "producer#example.com", password: "foobar",
password_confirmation: "foobar")
before { visit producer_path(#producer) }
it { should have_selector('h1', text: producer.name) }
it { should have_selector('title', text: producer.name) }
end
end
and the failure produced is:
Failures:
1) ProducerPages profile page
Failure/Error: before { visit producer_path(#producer) }
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"producers", :id=>nil}
# ./spec/requests/producer_pages_spec.rb:14:in `block (3 levels) in <top (required)>'
It looks, I do something wrong with creating the producer instance variable. I tried to make that a normal variable, but then I get this error:
1) ProducerPages profile page
Failure/Error: before { visit producer_path(producer) }
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"producers",
:id=>#<Producer id: nil, name: "Example Producer",
email: "producer#example.com", created_at: nil, updated_at: nil,
password_digest: "$2a$04$pXAEklj4nzYe48ojR5Ps/Oh8Ea9.QqKOajYBD2Rv0mQ9...",
remember_token: nil, admin: false, oid: nil, contact_name: nil,
street: nil, postal_code: nil, city: nil, country: nil, url: nil,
telephone: nil, cellular: nil, type: "Producer", producer_id: nil,
client_key: nil, product_count: 0>}
# ./spec/requests/producer_pages_spec.rb:14:in `block (3 levels) in <top (required)>'
the routes.rb file contains
resources :producers
What am I doing wrong?
I am only familiar with Rspec, but now I need to fix a library which uses Test::Unit.
I find out that when I reload the record, the association becomes nil
For example:
test "accepts nested attributes from subscription to user ()" do
#user = User.create(name:'Ash')
#subscription = #user.create_subscription()
puts "user: " << #user.inspect
puts "subscription: " << #user.subscription.inspect
#subscription.update_attributes({ :user_attributes => { :notification_comment => true } })
#user.reload
puts "user: " << #user.inspect
puts "subscription: " << #user.subscription.inspect
assert #user.subscription, "should have an subscription"
end
Outputs:
user: #<User id: 815823837, account_id: nil, name: "Ash", email: nil, settings: {}, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
subscription: #<Subscription id: 1, user_id: 815823837, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
user: #<User id: 815823837, account_id: nil, name: "Ash", email: nil, settings: {}, created_at: "2013-02-07 04:28:51", updated_at: "2013-02-07 04:28:51">
subscription: nil
Why does this happen? I did check and I can confirm that I can Subscription.find(#subscription.id) so it is saved in the database.