Undefined method error while running rspec test - ruby

All,
I am getting the following undefined method errors below when running my rspec tests. When I have gotten this error before I had a method misspelled or my order of execution caused it. I checked both along with some other posts on StackOverflow, but nothing helped. Can anyone offer any guidance?
Rspec Failures:
FFFF
Failures:
1) Post vote methods #up_votes counts the number of votes with value = 1
Failure/Error: expect(#post.up_votes ).to eq(3)
NoMethodError:
undefined method `up_votes' for #<Post:0x007fe92f381a38>
# ./spec/models/post_spec.rb:14:in `block (4 levels) in <top (required)>'
2) Post vote methods #down_votes counts the number of votes with values = -1
Failure/Error: expect(#post.down_votes ).to eq(2)
NoMethodError:
undefined method `down_votes' for #<Post:0x007fe92a18c228>
# ./spec/models/post_spec.rb:20:in `block (4 levels) in <top (required)>'
3) Post vote methods #points returns the sum of all down and up votes
Failure/Error: expect(#post.points ).to eq(1) # 3 - 2
NoMethodError:
undefined method `points' for #<Post:0x007fe92986c620>
# ./spec/models/post_spec.rb:26:in `block (4 levels) in <top (required)>'
4) Vote validations value validation only allows -1 or 1 as values
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError:
undefined method `up_votes' for nil:NilClass
# ./spec/models/vote_spec.rb:5:in `block (4 levels) in <top (required)>'
Post_rspec
require 'rails_helper'
describe Post do
describe "vote methods" do
before do
#post = Post.create(title: 'Post title', body: 'Post bodies must be pretty long.')
3.times { #post.votes.create(value: 1) }
2.times { #post.votes.create(value: -1) }
end
describe '#up_votes' do
it "counts the number of votes with value = 1" do
expect(#post.up_votes ).to eq(3)
end
end
describe '#down_votes' do
it "counts the number of votes with values = -1" do
expect(#post.down_votes ).to eq(2)
end
end
describe '#points' do
it "returns the sum of all down and up votes" do
expect(#post.points ).to eq(1) # 3 - 2
end
end
end
end
vote_spec file
describe Vote do
describe "validations" do
describe "value validation" do
it "only allows -1 or 1 as values" do
expect(#post.up_votes).to eq((-1) || eq(1))
end
end
end
end
Post.rb
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_many :votes
has_one :summary
belongs_to :user #means the post table has the user table's primary key in it
belongs_to :topic
mount_uploader :avatar, AvatarUploader
default_scope {order('created_at DESC')}
validates :title, length: {minimum: 5}, presence: true
validates :body, length: {minimum: 20}, presence: true
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
def markdown_body
(render_as_markdown).render(self.body).html_safe
end
private
def render_as_markdown
renderer = Redcarpet::Render::HTML.new
extensions = {fenced_code_blocks: true}
redcarpet = Redcarpet::Markdown.new(renderer, extensions)
#return redcarpet
end
end

For the post_spec.rb errors, check the Post model (see file app/models/post.rb) has the following methods defined in it:
up_votes
down_votes
points
Consider including the code for post.rb in your original question too.
For the vote_spec.rb errors, there is no #post variable, it will be nil. This error message hints at this:
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError: undefined method `up_votes' for nil:NilClass

Related

RSpec and active record validations

I'm trying to validate that the rating of a movie is greater than 0 and less than or equal to 5 and for that I'm using the "be_valid" in RSpec which seems to work when I check if the movie title is nil but it's not working for the rating.
I don't understand why
Model:
class Movie < ApplicationRecord
validates :title, presence: true
validates :rating, presence: true, numericality: { greater_than_or_equal_to: 0,less_than_or_equal_to: 5, only_integer: true }
end
Spec:
RSpec.describe Movie, type: :model do
# checking model validations
subject{described_class.new}
it "title must be present" do
subject.title = ""
expect(subject).not_to be_valid
end
it "rating must be greater than 0" do
subject.rating = 1
expect(subject.rating).to be_valid
end
it "rating must be less than or equal to 5" do
subject.rating = 5
expect(subject.rating).to be_valid
end
end
Error:
Movie
title must be present
rating must be greater than 0 (FAILED - 1)
rating must be less than or equal to 5 (FAILED - 2)
Failures:
1) Movie rating must be greater than 0
Failure/Error: expect(subject.rating).to be_valid
NoMethodError:
undefined method `valid?' for 1:Integer
# ./spec/models/movie_spec.rb:15:in `block (2 levels) in <top (required)>'
2) Movie rating must be less than or equal to 5
Failure/Error: expect(rating).to be_valid
NameError:
undefined local variable or method `rating' for #<RSpec::ExampleGroups::Movie:0x00007f8332f46fc0>
# ./spec/models/movie_spec.rb:20:in `block (2 levels) in <top (required)>'
You should use expect(subject).to be_valid in the other 2 test cases. You are getting the error because you are trying to validate subject.rating which is an integer.

Ruby - Capybara - ArgumentError: invalid keys

I'm executing a code, where i verify if the input is disabled, but an error occurs.
CODE
before(:each) do
visit 'https://training-wheels-protocol.herokuapp.com/dynamic_controls'
end
it 'quando habilita o campo' do
res = page.has_field? 'movie', disable: true
puts res
end
ERROR
ArgumentError:
invalid keys :disable, should be one of :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :checked, :unchecked, :disabled, :multiple, :readonly, :with, :type, :name, :placeholder
# ./spec/dynamic_control_spec.rb:8:in `block (2 levels) in <top (required)>'
Can someone help me?
The error message is telling you what options are valid to pass to has_field?. You should be passing disabled: true rather than :disable.

Why my ruby tests does not pass?

I have the following table TodoList :
class CreateTodoLists < ActiveRecord::Migration
def change
create_table :todo_lists do |t|
t.string :list_name
t.date :list_due_date
t.timestamps null: false
end
end
end
I create crud methods:
def create_todolist(params)
todolist = TodoList.create(params)
end
And i have the followging tests:
context "the code has to create_todolist method" do
it { is_expected.to respond_to(:create_todolist) }
it "should create_todolist with provided parameters" do
expect(TodoList.find_by list_name: "mylist").to be_nil
due_date=Date.today
assignment.create_todolist(:name=> 'mylist', :due_date=>due_date)
testList = TodoList.find_by list_name: 'mylist'
expect(testList.id).not_to be_nil
expect(testList.list_name).to eq "mylist"
expect(testList.list_due_date).to eq due_date
expect(testList.created_at).not_to be_nil
expect(testList.updated_at).not_to be_nil
end
end
When i launch the test give me the following errors:
assignment code has create_todolist method should create_todolist with provided parameters
Failure/Error: assignment.create_todolist(:name=> 'mylist', :due_date=>due_date)
ActiveRecord::UnknownAttributeError:
unknown attribute 'name' for TodoList.
# ./assignment/assignment.rb:25:in `create_todolist'
# ./spec/assignment_spec.rb:171:in `block (4 levels) in <top (required)>'
# ./spec/assignment_spec.rb:14:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `name=' for #<TodoList:0x007f96dd0d13f0>
# ./assignment/assignment.rb:25:in `create_todolist'
Finished in 0.14136 seconds (files took 1.66 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/assignment_spec.rb:168 # Assignment rq03 rq03.2 assignment code has create_todolist method should create_todolist with provided parameters
I think it's because params attributes does not match exactly the same TodoList attributes. How to modify my create_todolist to change keys values ?
Your field is called list_name, but you're passing :name => 'myList'.
The same for due_date and list_due_date.
Should be
assignment.create_todolist(list_name:'mylist', list_due_date: due_date)

ArgumentError: wrong number of arguments (1 for 0) when using afer_save

ArgumentError: wrong number of arguments (1 for 0)
from /Users/Castillo/Desktop/gainer/app/models/status.rb:13:in `update_remaining_nutrients'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:507:in `block in callback'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:504:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:504:in `callback'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:352:in `add_to_target'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:495:in `block in concat_records'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:493:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:493:in `concat_records'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:134:in `block in concat'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:149:in `block in transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/transactions.rb:208:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:148:in `transaction'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_association.rb:134:in `concat'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-3.2.11/lib/active_record/associations/collection_proxy.rb:116:in `<<'
from /Users/Castillo/Desktop/gainer/app/models/user.rb:65:in `eat'
from (irb):31
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p392/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
I want to call the update_remaining_nutrients method on status.rb whenever a meal is "eaten" by the user. When I call User.first.eat(Meal.first) I get the ArgumentError. Not sure why because I'm not passing the after_add method any arguments?
user.rb
class User < ActiveRecord::Base
has_many :meals
has_many :statuses
def eat(meal)
statuses.last.meals<<meal
end
end
status.rb
class Status < ActiveRecord::Base
attr_accessible :remaining_calories, :remaining_carbs, :remaining_protein, :weight, :user_id
belongs_to :user
has_many :meals, after_add: :update_remaining_nutrients
after_save :update_users_weight , :if => Proc.new {|a| a.weight_changed?}
def update_users_weight
self.user.weight.update_attributes(weight: self.weight)
end
def update_remaining_nutrients
puts "It Works!!!!!"
end
end
meal.rb
class Meal < ActiveRecord::Base
attr_accessible :name, :description, :clean_up, :homemade, :prep_time, :user_id, :status_id
belongs_to :user
belongs_to :status
has_many :ingredient_meals
has_many :ingredients, :through => :ingredient_meals
end
If you have a look at the Association callbacks section of the docs, you'll see this example:
class Project
has_and_belongs_to_many :developers, after_add: :evaluate_velocity
def evaluate_velocity(developer)
...
end
end
That's not the has_many relationship that you have but it is close enough. If you look at the evaluate_velocity method, you'll see that the developer in question is passed as an argument by the :after_add callback. You're getting an ArgumentError about your update_remaining_nutrients being called with one argument when it doesn't want any and that matches what the the example suggests would happen.
Try this:
def update_remaining_nutrients(meal)
# Do interesting things with `meal` in here...
end

wrong number of arguments ruby rspec

I'm trying to write unit tests for my code using rspec. I keep getting a "wrong number of arguments" error:
class MyClass
attr_accessor :env, :company,:size, :role, :number_of_hosts,:visability
def initialize(env, company, size, role, number_of_hosts, visability)
#env, #company, #size, #role, #number_of_hosts, #visability = env, company, size, role, number_of_hosts, visability
end
end
And here are my tests:
require_relative "../lib/MyClass.rb"
describe MyClass do
it "has an environment" do
MyClass.new("environment").env.should respond_to :env
end
it "has a company" do
MyClass.new("company").company.should respond_to :company
end
...
When I run rspec I get:
1) MyClass has an environment
Failure/Error: MyClass.new("environment").env.should respond_to :env
ArgumentError:
wrong number of arguments (1 for 6)
# ./lib/MyClass.rb:4:in `initialize'
# ./spec/MyClass_spec.rb:5:in `new'
# ./spec/MyClass_spec.rb:5:in `block (2 levels) in <top (required)>'
...
What am I missing?
EDIT
Sergio helped thanks...however
Sergio's answer worked...although I still have a further question:
Given the Class:
class Team
attr_accessor :name, :players
def initialize(name, players = [])
raise Exception unless players.is_a? Array
#name = name
raise Exception if #name && has_bad_name
#players = players
end
def has_bad_name
list_of_words = %w{crappy bad lousy}
list_of_words - #name.downcase.split(" ") != list_of_words
end
def favored?
#players.include? "George Clooney"
end
end
and spec...
require_relative "../lib/team.rb"
describe Team do
it "has a name" do
Team.new("random name").should respond_to :name
end
it "has a list of players" do
Team.new("random name").players.should be_kind_of Array
end
...
The tests pass without the same error...(This works fine: Team.new("random name"))
Any explanation?
Here is the error MyClass.new("environment"). As you have written def initialize(env, company, size, role, number_of_hosts, visability). So you should pass 6 parameters when you are calling MyClass#new method. But in practice you pass only one which is "environment". Thus you got the legitimate error - wrong number of arguments (1 for 6).

Resources