I have ran into a quick problem. I am getting a "undefined method `Factory'" for the user_spec page. I believe I have the incorrect syntax for " let(:user) { Factory(:user) }". However I can't come up with one that works.
Failure/Error: let(:user) { Factory(:user) }
NoMethodError:
undefined method `Factory' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fc7ac31e6a8>
If someone can take a look at my code and help me out that would be appreciated as I am almost done testing for the password reset.
user_spec.rb:
require 'spec_helper'
describe User do
describe "#send_password_reset" do
let(:user) { Factory(:user) }
it "generates a unique password_reset_token each time" do
user.send_password_reset
last_token = user.password_reset_token
user.send_password_reset
user.password_reset_token.should_not eq(last_token)
end
it "saves the time the password reset was sent" do
user.send_password_reset
user.reload.password_reset_sent_at.should be_present
end
it "delivers email to user" do
user.send_password_reset
last_email.to.should include (user.email)
end
end
end
the Factory Girl method is the following:
let(:user) { FactoryGirl.create(:user) }
Replace Factory with FactoryGirl, they changed that to remove ambiguity and to let the useful Factory namespace available.
Related
I'm trying to follow Mike Hartl's tutorial with RSpec. I've reached the password reset integration test, and so far I was doing well. Then I got to the line that said user = assigns(:user)
I searched for an answer so here is what I have and my error.
Failures:
PasswordResets Password resets email input valid email sends password and redirects to root
Failure/Error: expect(assigns(:user)).to eq([user])
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::PasswordResets::PasswordResets::EmailInput:0x007fc5d16b0ca8>
# ./spec/requests/password_resets_spec.rb:26:in `block (4 levels) in <top (required)>'
require 'rails_helper'
RSpec.describe "PasswordResets", type: :request do
describe "Password resets" do
before do
ActionMailer::Base.deliveries.clear
#valid_user = create(:user)
end
describe "unsuccessful password reset" do
it "flashes danger when email is blank" do
get new_password_reset_path(#valid_user.id)
post password_resets_path, params: { password_reset: { email: " " } }
expect(flash[:danger]).to be_present
expect(page).to render_template(:new)
end
end
describe "email input" do
it "valid email sends password and redirects to root" do
post password_resets_path, params: { password_reset: { email: #valid_user.email } }
expect(#valid_user.reset_digest).not_to match (#valid_user.reload.reset_digest)
expect(ActionMailer::Base.deliveries.size).to eq(1)
expect(flash[:info]).to be_present
expect(page).to redirect_to root_url
expect(assigns(:user)).to eq([user])
end
end
end
end`
The tutorial I'm following https://www.railstutorial.org/book/password_reset 12.18
I'm not sure what else to do.
Your test is erroring because you haven't defined a user variable at that point in your test. You have defined #valid_user. My guess is your test would pass if you change:
expect(assigns(:user)).to eq([user])
to
expect(assigns(:user)).to eq(#valid_user)
I try to create test for users-factories.But when I running test, 'rspec' show me an error
Failure/Error: expect(:user).to be_valid
NoMethodError:
undefined method `valid?' for :user:Symbol
this is my user_spec.rb
require 'rails_helper'
RSpec.describe do
it "has a valid factory" do
user = FactoryGirl.create(:user)
expect(:user).to be_valid
end
end
and this is users-factories(with 'faker' gem)
FactoryGirl.define do
factory :user do
email Faker::Internet.email
password Faker::Internet.password(8)
end
end
how fix and why this method don't work?
sorry for my bad English
Here is a fix :
RSpec.describe do
it "has a valid factory" do
user = FactoryGirl.create(:user)
expect(user).to be_valid
end
end
You passed the symbol :user as an argument to the expect(:user), which you shouldn't. You should pass the local variable user, you have created, and passed to it expect(user).
I have this spec that I want to translate to MiniTest.
describe User do
subject { build(:user, provider: 'foo') }
# don't validate presence of password when provider is present
it do
should_not validate_presence_of(:password)
end
end
I tried this. I am getting an error of undefined method 'should_not' for UserTest
class UserTest < ActiveSupport::TestCase
def setup
#user = build_stubbed(:user)
end
test "responds to name" do
assert_respond_to #user, :name
end
should validate_presence_of(:password)
test "do not validate presence of password when provider is present" do
build_stubbed(:user, provider: 'foo')
should_not validate_presence_of(:password)
end
end
I want to change the context for one test, where the subject gets a provider attribute, which should disable the presence validator on the password field.
Here's the full error:
UserTest#test_presence_of_password:
NoMethodError: undefined method `should_not' for #<UserTest:0x007feaa82c1c68>
test/models/user_test.rb:45:in `block in <class:UserTest>'
I found that the better way to do this is to revert to good old MiniTest:
test "uniqueness of email with a different provider" do
email_user = create(:user, email: "foo#bar.com")
facebook_user = build_stubbed(:facebook_user, email: "foo#bar.com")
assert facebook_user.valid?, "should be valid with same email if provider is different"
end
Take a look at the minitest-rails-shoulda gem. If you use it I assume the test would look like this:
describe User do
subject { build_stubbed(:user) }
it { must validate_presence_of(:password) }
describe "when a provider is present" do
subject { build_stubbed(:user, provider: 'foo') }
it { wont validate_presence_of(:password) }
end
end
From chapter10.23, file: spec/requests/authentication_pages_spec.rb
require 'spec_helper'
describe "Authentication" do
.
.
.
describe "authorization" do
describe "for non-signed-in users" do
let(:user) { FactoryGirl.create(:user) }
.
.
.
describe "in the Microposts controller" do
describe "submitting to the create action" do
before { post microposts_path }
specify { expect(response).to redirect_to(signin_path) }
end
describe "submitting to the destroy action" do
before { delete micropost_path(FactoryGirl.create(:micropost)) }
specify { expect(response).to redirect_to(signin_path) }
end
end
.
.
.
end
end
end
when i tried to pass the test. one of them failed and the message is shown below:
1) Authentication authorization for non-signed-in users in the Microposts controller
submitting to the destroy action
Failure/Error: before { delete micropost_path(FactoryGirl.create(:micropost)) }
ActiveRecord::RecordInvalid:
Validation failed: User can't be blank
# ./spec/requests/authentication_pages_spec.rb:90:in `block (6 levels) in <top (required)>'
the problem is I discontinued from learning ROR for a while so I don't know where I did wrong and why the test failed with this message.
Can anyone help?
I think your FactoryGirl.create(:micropost) is invalid! It looks like you have a vlidation of user on presense in Micropost but you did not specify user in factory.
You should define factory for micropost as
FactoryGirl.define do
factory :micropost do
...
user
...
end
end
or call Factory.create with existed user (you define user before in a let-block): FactoryGirl.create(:micropost, user: user)
You should choose a way according to your needs (workflow logic)
I am trying to verify that the validators are working correctly on my model, and for that I am using Rspec and Capybara. Here is my code.
describe "#when registering" do
before { visit new_record_path }
describe "#with invalid information" do
describe "#should not modify database" do
subject { -> { click_button submit } }
it { should_not change(Pet, :count) }
it { should_not change(Owner, :count) }
end
end
end
end
When I run the specs, i get an error: "undefined method 'model_name' for NilClass:Class"
What could be causing rspec to think my model is nil?
Thanks!
You should not test your validations with a feature/acceptance test, it should be with a model test. Then for each form you could test an error is raised if something is invalid instead of testing every error through acceptance tests. For each model it should be something like so:
describe Pet do
describe "validations" do
# These can echo any model validation
it "is invalid if attribute is not present" do
Pet.new(:attribute => "Invalid Item").should_not be_valid
end
end
end
or with Factory Girl:
describe Pet do
describe "validations" do
it "is invalid if attribute is not present" do
build(:pet, :attribute => "Invalid Item").should_not be_valid
end
end
end
Then in an acceptance test you can have something like:
it "displays an error if validation fails" do
visit new_pet_path
#Something to make the form submission fail, not everything
fill_in("Attribute", :with => "")
click_button("Create Pet")
page.should have_content("can't be blank")
current_path.should == pets_path
end
This will help to keep your acceptance tests light and test the validations in the model where it belongs. Hope this helps!