No Method Error while testing with Rspec in Rails - ruby-on-rails

I get a No Method Error while Testing with Rspec. Here is my code for the Test:
scenario 'admin updates a commissionrate' do
create(:assignment, user_id: #user.id, role_id: 1)
sign_in(#user)
commissionrate = create(:commissionrate, rate: 0.05)
visit edit_commissionrate_path(commissionrate)
fill_in 'rate', with: 0.05
click_on 'Eingaben speichern'
expect(page).to have_content('erfolgreich')
end
and this is the factory for the commissionrate:
require 'faker'
FactoryGirl.define do
factory :commissionrate do
commissionrate { Faker::Number.number(0.05)}
end
end
I receive the error: undefined method 'commissionrate=' for #<Commissionrate:0xbc5ac10>
Any ideas where I'm wrong?

I feel you are supposed to assign factory values to your fields/columns in your model. Is commissionrate a field or should you actually rename it as rate? Just check that and see. Also, it would be useful if you can give information such as the model name and the columns.

Seems like you're trying to assign commissionrate, which is not a valid attribute of model commissionrate.
Try changing the line
commissionrate { Faker::Number.number(0.05)}
to
rate { Faker::Number.number(0.05)}
I can see that there is a column rate in commissionrate model in this line commissionrate = create(:commissionrate, rate: 0.05).

Related

How to write RSpec to check if associated record exists?

I am beginner to RSpec. I am having a model teacher that has_many :lessons. Here is my FactoryGirls records:
spec/factories/lessons.rb
FactoryGirl.define do
factory :lesson do
title "Rspec test"
description "test description"
company_name "narola pvt"
association :teacher
location "Zwanenplein 34"
days_to_pay 2
end
end
spec/factories/teachers.rb
FactoryGirl.define do
factory :teacher do
first_name "Teacher's name"
last_name "Teacher's last name"
address "los angeles"
city "california"
zip_code "12345"
country "USA"
birthdate nil
phone nil
password "password"
email { "example#{SecureRandom.uuid}#email.dummy" }
end
end
Following is my try with models test:
spec/models/teacher_spec.rb
require 'rails_helper'
RSpec.describe Teacher, type: :model do
let(:teacher) { FactoryGirl.create(:teacher) }
it "should have at least one lesson" do
config.expect_with(Lesson.where(teacher_id: teacher)){|c| c.syntax = :should}
end
end
I am willing to write a rspec test case to find if lesson exists for particular lesson.
Please try this:
it "should have at least one lesson" do
expect(Lesson.where(teacher_id: teacher.id)).to exist
end
Let me know if it's work for you. I haven't try this.
it "should have at least one lesson" do
expect(Lesson.where(teacher_id: teacher.id).exists?).to be_truthy
end
This would be faster because of the use of 'exists?' method compared to
expect(Lesson.where(teacher_id: teacher.id)).to exist
Underlying query execution due to use of 'exists?' the method is fast. More details are here ->
https://www.ombulabs.com/blog/benchmark/performance/rails/present-vs-any-vs-exists.html

How to output values of rspec subject to debug?

I can't figure out why my validation is failing. How can I output the value of my rspec subject i.e. model built from factory_girl
I am doing this test which is failing:
let(:factory_instance) { build(:user)}
it { should allow_value("abc123").for(:password) }
Test is failing, it has some errors like:
"can't be blank" (attribute: email, value: nil)
I want to output the value user that is loaded using factory_girl to see what is going on.
Change your it statement to a do block and then on the first line just log out user:
it "should do something" do
p "#{user.inspect}"
# use expect here
user.email = "valid#email.com"
user.password = "abc123"
expect(user.save).to eq(true)
end

Factorygirl , I can't express the association of 1 on 1 (has_one) with rspec

I want to test #create in Decidingscontroller , and Deciding model has undertaking_id column in association with Undertaking model , and has asking_id column in association with Asking model.
So, My factories/decidings.rb is below.
factory :deciding do
after(:build) do |deciding|
deciding.asking ||=build(:asking, deciding: deciding)
deciding.undertaking ||=build(:undertaking, deciding: deciding)
end
end
and My spec/controllers/decidings_controller_spec.rb is below.
RSpec.describe DecidingsController, type: :controller do
describe '#create' do
before do
#deciding=build(:deciding)
end
context 'correct_user login' do
before do
login_user(#deciding.asking.user)
end
it 'creates with deciding +1' do
expect{post :create , undertaking_id: #deciding.undertaking_id , asking_id: #deciding.asking_id}.to change(Deciding , :count).by(1)
end
end
end
end
but #deciding in this case is below.
#<Deciding id: nil, asking_id: nil, undertaking_id: nil, created_at: nil, updated_at: nil>
so I can't create test because undertaking_id and asking_id is nil.
Why is undertaking_id and asking_id nil? Please help me...
Anyway , My factories/asking.rb is below.
FactoryGirl.define do
factory :asking do
association :user
sequence(:content){|i| "お願いします#{i}"}
end
end
The ids are nil because the records are not persisted. When you use build method, it does not save a record in the database. If a record is not saved, it cannot have ID. Use create method instead.
Try this:
factory :deciding do
after(:build) do |deciding|
deciding.asking ||= create(:asking)
deciding.undertaking ||= create(:undertaking)
end
end

RSpec - model uniqueness testing issue

I'm trying to make some simple model test:
/app/models/album.rb:
class Album < ActiveRecord::Base
has_many :slides, dependent: :restrict_with_exception
validates :name, presence: true
end
/spec/model/album_spec.rb:
require 'spec_helper'
describe Album do
before do
#album = Album.new(name: 'Example Album')
end
describe "when album name is already taken" do
before do
another_album = #album.dup
another_album.save
end
it { should_not be_valid }
end
end
I was expecting it to fail first (as I have no validates :uniqueness and index on the name field) but it passed. So I changed:
it { should_not be_valid }
to
it { should be_valid }
To see what's going on and this is what I got:
1) Album when album name is already taken should be valid
Failure/Error: it { should be_valid }
expected #<Album id: nil, name: nil, created_at: nil, updated_at: nil> to be valid, but got errors: Name can't be blank
# ./spec/models/album_spec.rb:14:in `block (3 levels) in <top (required)>'
I would like to ask you what I did wrong.
One more thing is if I can/should use expect rather than should syntax here ? I read somewhere that should is a bit deprecated and not expect is recomended but I don't know how to use it for model testing (I have it on my Controller/View test in form of expect(page) or expect(current_path). What argument can I use for model ?
I have never seen the it syntax that you are using. First thing, I would checkout the quick start documentation available here: https://github.com/rspec/rspec-rails#model-specs and then make sure that you are familiar with this set of docs as well: http://rspec.info/
From the example on github:
require "spec_helper"
describe User do
it "orders by last name" do
lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
end
end
You would want to change your second describe to an it and then use one or more expect to determine if the test passes. it takes a string that appears in the test output. So generally you want to make it something expressive. Additionally there is no need to use before blocks here. You can do everything in the it block:
require 'spec_helper'
describe Album do
it "fails validation when album name is already taken" do
album = Album.new(name: 'Example Album')
another_album = album.dup
expect {another_album.save!}.to raise_error(ActiveRecord::RecordInvalid,'Validation failed: This question is no longer active.')
end
end
Setup an explicit subject before your example:
subject {#album}
it { should_not be_valid }
Currently, as per the failure error#<Album id: nil, name: nil, created_at: nil, updated_at: nil> an implicit blank instance of Album is created as no explicit subject is found before the example.

Rspec Create multiple posts to check ranking

Afternoon All,
I've just starting learning the testing side of rails and having some trouble with this below.
Let me quickly explain what I'm trying to test. If a user creates 10 approved snippets their rank should == "Author". A snippet is created on a book which I have listed in the factories but my code is all messed up and I'm not sure how I would write this.
Here is the code I've been playing with for the testing:
describe "ranking" do
let!(:book) { Book.create }
let!(:snippet) { FactoryGirl.create(:snippet1, :book1 => book) }
context "should be author after 10 approved posts" do
10.times do
FactoryGirl.create(:snippet1)
end
user.user_rank.should == "Author"
end
end
Here are my factories:
FactoryGirl.define do
factory :admin2, class: User do
first_name "admin1"
last_name "minstrator"
password "admin1234"
profile_name "profilename"
email "admin1#admin.com"
password_confirmation "admin1234"
admin true
end
factory :user2, class: User do
first_name "user2"
last_name "man2"
password "user1234"
profile_name "profilename"
email "user2#user.com"
password_confirmation "user1234"
admin false
end
factory :book1, class: Book do
title "Book1"
approved true
size 0
end
factory :snippet1, class: Snippet do
content "Snippet1"
approved true
end
end
EDIT: Error and related code:
app/models/snippet.rb:32:in `size_limit': undefined method `size' for nil:NilClass (NoMethodError)
This relates to a validation in the model shown below:
BOOK_SIZE = {
0 => {'per' => 500, 'total' => 15000},
1 => {'per' => 700 , 'total' => 30000},
2 => {'per' => 1000, 'total' => 50000}
}
def size_limit
book_limit = self.book.size.to_i
word_count = self.content.scan(/\w+/).size.to_i
current_snippets_size = (self.book.get_word_count || 0) + word_count
errors.add(:base, "Content size is too big") unless word_count < BOOK_SIZE[book_limit]['per'] && current_snippets_size < BOOK_SIZE[book_limit]['total']
end
I think your snippet1 factory should have user_id or something like that. now you create 10 snippet without association
edit: now I read your edit. but hire is almost the same. your snippet1 factory haven't any book so error on this
self.book.size.to_i
Your let(:snippet) clause uses a :book1 attribute, but the code is checking the self.book – could that be it?
Either way, the snippet.rb excerpt you've listed has two references to .size - without knowing your line numbers, it's hard for us to tell which one is throwing the error.
So either the book attribute or the content attribute is returning nil – and so when you call size on that nil attribute you get the error that's happening.
If snippet is only valid with a book reference and a non-nil content, add validations for those conditions. If there are situations where those attributes could be nil, make sure that your code makes allowances for that.

Resources