Trouble on testing a model method call in a spec file - ruby-on-rails

I am using Ruby on Rails 3.0.10, RSpec 2 and FactoryGirl. I am trying to validate user account data.
In my model I have:
class Users::Account < ActiveRecord::Base
...
def get_account_password_salt(password)
make_user_account_password_salt(password)
end
end
In my spec file I have
it "should have a valid password salt" do
users_account.password_salt.should == Users::Account.get_account_password_salt('123456')
end
When I run the rspec command I get the following error:
Users::Account should have a valid password salt
Failure/Error: users_account.password_salt.should == Users::Account.get_account_password_salt('123456')
NoMethodError:
undefined method `get_account_password_salt' for #<Class:0x0000010729c9f0>
What is the problem and how can I solve that?
I also tryed to use ::Users::Account.get_account_password_salt('123456') (note the :: at the beginning) but it still doesn't work.

SOLUTION
The problem was that I have to run
users_account.get_account_password_salt('123456')
instead of:
Users::Account.get_account_password_salt('123456')

Related

RoR : integration test fail

I have 2 integrations tests, here how it's look :
class TagFlowTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
setup do
sign_in FactoryGirl.create(:admin)
#partner = create(:partner)
end
test 'can see the list of partners' do
get '/partners'
assert_response :success
assert_select 'tr', 2
end
... more tests below ...
The second test looks the same
The thing is that when a launch rails test on this test, it's working fine. But when I launch :
rails test /test/
I got an error :
UnexpectedError: ActiveRecord::RecordNotUnique: PG::UniqueViolation:
ERROR: duplicate key value violates unique constraint
"index_users_on_email"
I understand that the issue come from
sign_in FactoryGirl.create(:admin)
When I delete this line on the other test, it's working.
But if I do that, I cannot test one test only. How can I do the resolve this ?
UnexpectedError: ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_users_on_email"
So what does this error mean? You have some validation in the model level or the db level which will not let you have the duplicate email for Admin.
So I presume that the factory you used to create Admin, is not creating unique email addresses.
Try this
FactoryGirl.define do
factory :admin do
# your code
email { Faker::Internet.email }
end
end
But this thing requires faker gem. If you don't want to use a gem just for this, try using sequences in factory girl.
Also it's good to have the database in a clean state, when running tests. Consider using https://github.com/DatabaseCleaner/database_cleaner

Fixtures in mail preview

Having the following mailer previewer code:
class RegistrationMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/registration_mailer/welcome
def welcome
RegistrationMailer.welcome users(:one)
end
end
(full file).
Which is unable to reach my fixtures (users(:one)), return a 500 error status and print out the following error:
NoMethodError: undefined method `users' for #RegistrationMailerPreview
Can we get fixtures entries from mailer previewer?
If yes, I would like to know how to do that.
I have seen that should be possible here, but I can't require test_helper in this file (I don't know why) and I don't understand the difference between ActionMailer::TestCase and ActionMailer::Preview.
If no, is there a way to preview the mail without sending as a parameter User.first, since I could do my tests on a machine on which there is no data filled in the database.
I don't know about the default fixture framework, but I can say using FactoryBot for my fixtures that I was able to use them in my mailer previews simply by prepending the build/create methods with FactoryBot. I didn't need to require anything at the top of the file. i.e.:
class RegistrationMailerPreview < ActionMailer::Preview
def welcome
user = FactoryBot.create(:user)
RegistrationMailer.welcome(user)
end
end
To answer your second question, you could also simply replace the fixture line above with user = User.new(firstname: "Joe"). That would create a new user to use in the preview without persisting it to the database.

rspec undefined method `sequence' for 1:Fixnum

I am writing a spec test in rails using rspec. One of the models I am testing has an attribute of sequence on it, and it is conflicting with rspec (from what I have found), but I have not been able to find a work around.
Here is my code
lessons.rb (factory)
FactoryGirl.define do
factory :lesson do
version_id 1
add_attribute :sequence, 1 # this is the field
name "Lesson Name"
description "An Example Lesson Description"
group_id 1
content "here is some example context"
passing_quiz_difficulty 2
survey_id 1
status 1
staff_content "example staff content"
lesson_type_id 1
end
end
method I'm testing
def second_response?(lesson)
self.lessons.where('sequence < ?', lesson.sequence).first
end
controller
def show
...
#part_two = true if #reveal_step.second_response?(#lesson)
...
end
rspec stack trace
Failure/Error: expect(#reveal_step.second_response?(lesson_1.id)).to eql true
NoMethodError: undefined method `sequence' for 1:Fixnum
This method works fine in the application, but I need to write a test for it, and I cannot find a work around with the sequence attribute, and I cannot leave it out because this whole method and flow of this part of the app is dependent on the sequence attr. Does anyone know of a workaround to use? or another way I could approach this? Any help would be appreciated.
Your expectation is passing a number, lesson_1.id, into a method that expects a lesson. That ID does not have a sequence method, while lessons do.

Rspec-rails 4 error: ActiveModel::ForbiddenAttributesError

I have an application running in rails 4.1 using mongoid as the orm. I created a model called User which has an attribute email. I am using RSpec for tests. I created the following spec
require 'spec_helper'
describe 'User' do
before(:each) do
#attr = {
user: {
email: "rahul#gmail.com"
}
}
end
it "should create a valid User instance" do
param = ActionController::Parameters.new(#attr)
param.require(:user).permit!
User.create!(param)
end
end
when I run the spec, I get the following error
Failure/Error: User.create!(param)
ActiveModel::ForbiddenAttributesError:
ActiveModel::ForbiddenAttributesError
I know this is related to strong parameters but couldn't figure out what I am doing wrong.
From the fine manual:
require(key)
[...] returns the parameter at the given key [...]
So saying param.require(:user) does nothing at all to param, it merely does an existence check and returns param[:user].
I think you want to say something more like this:
param = ActionController::Parameters.new(#attr)
User.create!(param.require(:user).permit!)
That usage would match the usual:
def some_controller_method
#user = User.create(user_param)
end
def user_param
param.require(:user).permit!
end
usage in controllers.

How to stub error raising using Rspec in Rails?

I'm new to Rails and Rspec and I'm using Rspec to test this controller method which includes exception handling:
def search_movies_director
#current_movie = Movie.find(params[:id])
begin
#movies = Movie.find_movies_director(params[:id])
rescue Movie::NoDirectorError
flash[:warning] = "#{#current_movie} has no director info"
redirect_to movies_path
end
end
I can't figure out how to correctly test the said path: after invalid search (when error is received) it should redirect to the homepage. I tried something like this:
describe MoviesController do
describe 'Finding Movies With Same Director' do
#some other code
context 'after invalid search' do
it 'should redirect to the homepage' do
Movie.stub(:find)
Movie.stub(:find_movies_director).and_raise(Movie::NoDirectorError)
get :search_movies_director, {:id => '1'}
response.should redirect_to movies_path
end
end
end
end
After running the test fails with an error: NameError: uninitialized constant Movie::NoDirectorError
How to fake raising an error in this test so it actually checks whether redirect happens?
Thanks!
UPDATE:
As nzifnab explained, it couldn't locate Movie::NoDirectorError. I forgot to define this exception class. So I added it to app/models/movie.rb :
class Movie < ActiveRecord::Base
class Movie::NoDirectorError < StandardError ; end
#some model methods
end
This solved my problem and this test passes.
You're very close. You need to add any_instance in there.
Movie.any_instance.stub(:find_movies_director).and_raise(Movie::NoDirectorError)
edit: I misread the post. The above would work given an instance of Movie, but not for OP's question.
The error indicates it doesn't know where that Movie::NoDirectorError exception class is defined. You might need to specifically require the file where that class is defined or the test may not be able to find it.
Rails will automatically attempt to locate any constant missing constants using a conventional file directory format. It will look for a file in the load_path at movie/no_director_error and movie based on the name of the constant. If the file is not found or the file doesn't define the expected constant than you'll need to specifically require the file yourself.
In Rails 4.1:
verse_selector = double("VerseSelector", select_verses: ActiveRecord::RecordNotFound.new("Verses not found"))
verse_selector.select_verses will now return an ActiveRecord::RecordNotFound

Resources