Net.tutorialplus.com -Rspec tutorial- NoMethodError - ruby-on-rails

I am following Rspec testing tutorial on Net.Tutsplus.com.
I've found problem I couldn't solve. Here the thing.
When I run test:
C:\projekt>rspec spec/library_spec.rb --format nested
I get:
C:/projekt/spec/library_spec.rb:35:in `block (3 levels) in <top (required)>': un
defined method `books' for nil:NilClass (NoMethodError)
library_spec.rb looks like that:
require "spec_helper"
describe "Library Object" do
before :all do
lib_arr = [
Book.new("JavaScript: The Good Parts", "Douglas Crockford", :development),
Book.new("Designing with Web Standarts", "Jeffrey Zeldman", :design),
Book.new("Don't Make me Think", "Steve Krug", :usability),
Book.new("JavaScript Patterns", "Stoyan Sefanov", :development),
Book.new("Responsive Web Design", "Ethan Marcotte", :design)
]
File.open "books.yml", "w" do |f|
f.write YAML::dump lib_arr
end
end
before :each do
#lib = Library.new "books.yml"
end
describe "#new" do
context "with no parameters" do
it "has no books" do
lib = Library.new
lib.books.length.should == 0
end
end
context "with a yaml file name parameters " do
it "has five books"
#lib.books.length.should == 5
end
end
end
Due to tutorial instructions I changed library.rb to:
require 'yaml'
class Library
attr_accessor :books
def initalize lib_file = false
#lib_file = lib_file
#books = #lib_file ? YAML::load(File.read(#lib_file)) : []
end
end
According to tutorial it should solve "books-NoMethodError" problem but it still apper.
Where is the problem?
Thanks for help!

undefined method books for nil:NilClass (NoMethodError) just means that you are calling a method books on something that is nil, in this case #lib.
You need to place the before(:each) hook that defines #lib inside a context or describe block, in your code it is not available in the describe '#new' block.
Also, you were missing a do after defining the it "has five books" spec.
I've corrected these errors below:
describe "#new" do
before :each do
#lib = Library.new "books.yml"
end
context "with no parameters" do
it "has no books" do
lib = Library.new
lib.books.length.should == 0
end
end
context "with a yaml file name parameters " do
it "has five books" do
#lib.books.length.should == 5
end
end
end

Related

rspec Ruby on Rails uninitialized constant RecipesController::Recipes

hello i'm doing some test of my application with Rspec (this is my very first time i'm using it)
this is my test file located in spec/controllers/recipes_controller_spec.rb:
require 'spec_helper'
describe RecipesController do
render_views
describe "index" do
before do
Recipe.create!(name: 'Baked Potato w/ Cheese')
Recipe.create!(name: 'Garlic Mashed Potatoes')
Recipe.create!(name: 'Potatoes Au Gratin')
Recipe.create!(name: 'Baked Brussel Sprouts')
xhr :get, :index, format: :json, keywords: keywords
end
subject(:results) { JSON.parse(response.body) }
def extract_name
->(object) { object["name"] }
end
context "when the search finds results" do
let(:keywords) { 'baked' }
it 'should 200' do
expect(response.status).to eq(200)
end
it 'should return two results' do
expect(results.size).to eq(2)
end
it "should include 'Baked Potato w/ Cheese'" do
expect(results.map(&extract_name)).to include('Baked Potato w/ Cheese')
end
it "should include 'Baked Brussel Sprouts'" do
expect(results.map(&extract_name)).to include('Baked Brussel Sprouts')
end
end
context "when the search doesn't find results" do
let(:keywords) { 'foo' }
it 'should return no results' do
expect(results.size).to eq(0)
end
end
end
end
when i try to execute it by the command:
bundle exec rspec spec/controllers/recipes_controller_spec.rb
i fail all my tests with this error:
Failure/Error: xhr :get, :index, format: :json, keywords: keywords
NameError:
uninitialized constant RecipesController::Recipes
# ./app/controllers/recipes_controller.rb:4:in `index'
# ./spec/controllers/recipes_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
i've tried to look all my code but i haven't find out the error
NameError: uninitialized constant RecipesController::Recipes
means you used Recipes instead of Recipe somewhere (line 4 in index) in controller, and since your model is called Recipe (singular), you're getting NameError exception.

Testing Rails helper with Rspec: undefined local variable or method `request'

I have a helper method that uses 'request' to determine the URL. However, rspec can't seem to find request. I thought request was available to all front-facing tests?
How can I account for the request method in my spec?
Helper Spec
require 'spec_helper'
describe ApplicationHelper do
describe "full_title" do
it "should include the page title" do
expect(full_title("help")).to include('help')
end
end
end
Helper methods
def full_title(page_title)
if staging? # causing the issue
base_title = "Staging"
else
base_title = "Company Name"
end
if page_title.empty?
"#{base_title} | Tag line "
else
"#{base_title} | #{page_title} "
end
end
def staging? # the request here seems to be the problem
request.original_url.include? "staging"
end
Rspec error
Failure/Error: expect(full_title("help")).to include('help')
NameError:
undefined local variable or method `request' for #<RSpec::ExampleGroups::ApplicationHelper_2::FullTitle:0x00000106260078>
Thanks in advance.
First off: request is only available in the controller tests (and even then only in the request specs I think), helper tests are really basic and isolated. Which is good. Your helper code should be really minimal and normally only work on the input it receives.
However this is pretty easily solvable by using stubbing.
So write something like
#note, OP needed to replace 'helper' with 'self'for Rails 4.0.0 and Rspec 3.0
require 'rails_helper'
describe ApplicationHelper do
describe "full_title" do
context "in staging" do
it "should include the page title" do
helper.should_receive(:staging?).and_return(true)
expect(full_title("help")).to include('help')
end
end
context "not in staging" do
it "should include the page title" do
helper.should_receive(:staging?).and_return(false)
expect(full_title("help")).to include('help')
end
end
end
end
Which is imho a very clear, and then you write separate tests for your staging? method:
describe "staging?" do
context "when in staging" do
it "returns true" do
helper.stub(:request) { OpenStruct.new(original_url: 'staging') }
expect( helper.staging? ).to be true
end
end
context "when not in staging" do
it "returns false" do
helper.stub(:request) { OpenStruct.new(original_url: 'development') }
expect(helper.staging?).to be false
end
end
end
end
Some small remarks: ruby default indentation is 2 spaces.
Secondly, your function now literally says return true if true, ideally it should be written like
def staging?
request.original_url.include? "staging"
end

rspec shared_examples cannot be nested

I want to write two tests and both partially rely on the same behavior, approximately as seen below. This is something I would like to pull out of my code, and it seems like shared contexts are how to do it, but there is a scoping problem.
require 'spec_helper'
def getlink()
['link','id']
end
describe 'static pages' do
hash = {'link' => {'id' => 'payload'},'link_' => {'id_' => 'payload_'}}
subject{hash}
shared_examples_for 'it is mapped correctly' do |link, id|
it 'is mapped correctly' do
expect(subject[link]).to have_key(id)
end
end
describe 'the payload is correct' do
it_should_behave_like 'it is mapped correctly', 'link','id'
it 'has the correct value' do
expect(subject['link']['id']).to eq('payload')
end
end
# works fine
describe 'the get link function works correctly' do
it 'links inside the has' do
link = getlink()
expect(subject[link[0]]).to have_key(link[1])
end
end
# fails saying that it_should_behave_like is not defined.
describe 'the get link function works correctly with shared examples' do
it 'links inside the has' do
link = getlink()
it_should_behave_like 'it is mapped correctly', link[0], link[1]
end
end
end
why is this designed to fail? Is there an idiomatic way to accomplish this?
Like other it methods, it_should_behave_like is not defined within other it methods. You can see that you get the same exception when nesting regular its:
require 'rspec/autorun'
describe 'it inside it' do
it 'outer' do
it 'inner' do
end
end
end
#=> 1) it inside it outer
#=> Failure/Error: Unable to find matching line from backtrace
#=> NoMethodError:
#=> undefined method `it' for #<RSpec::Core::ExampleGroup::Nested_1:0x28e1e60>
#=> # stuff.rb:37:in `block (2 levels) in <main>'
To fix the exception, you could simply get rid of the outer it:
describe 'the get link function works correctly with shared examples' do
link = getlink()
it_should_behave_like 'it is mapped correctly', link[0], link[1]
end
If the outer it is being used to describe some information, you could make it a context instead:
describe 'the get link function works correctly with shared examples' do
context 'links inside the has' do
link = getlink()
it_should_behave_like 'it is mapped correctly', link[0], link[1]
end
end

RSpec - How to create helper method available to tests that will automatically embed "it" tests

I am new to ruby/rails/rspec etc.
Using rspec 2.13.1, I want to create a module with a method that can be called from my tests resulting to subsequent calls of the "it" method of the RSpec::Core::ExampleGroup.
My module:
require 'spec_helper'
module TestHelper
def invalid_without(symbols)
symbols = symbols.is_a?(Array) ? symbols : [symbols]
symbols.each do |symbol|
it "should not be valid without #{symbol.to_s.humanize}" do
# Gonna nullify the subject's 'symbol' attribute here
# and expect to have error on it
end
end
end
end
The code above was added to:
spec/support/test_helper.rb
and in my spec_helper.rb, in the RSpec.configure block, I added the following:
config.include TestHelper
Now, in a test, I do the following:
describe Foo
context "when invalid" do
invalid_without [:name, :surname]
end
end
Running this, I get:
undefined method `invalid_without' for #<Class:0x007fdaf1821030> (NoMethodError)
Any help appreciated..
Use shared example group.
shared_examples_for "a valid array" do |symbols|
symbols = symbols.is_a?(Array) ? symbols : [symbols]
symbols.each do |symbol|
it "should not be valid without #{symbol.to_s.humanize}" do
# Gonna nullify the subject's 'symbol' attribute here
# and expect to have error on it
end
end
end
describe Foo do
it_should_behave_like "a valid array", [:name, :surname]
end

RSpec2 & Rails3, issue with the basics of testing helpers

That's certainly trivial but can't figure out what goes wrong.
Helper : app/helpers/bookings_helper.rb
module BookingsHelper
def booking_price(booking)
"something"
end
end
Helper spec : spec/helpers/bookings_helper_spec.rb
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe BookingsHelper do
describe "#booking_price" do
helper.booking_price.should == 'something'
end
end
Error
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.4/lib/active_support/whiny_nil.rb:48:in `method_missing': undefined method `booking_price' for nil:NilClass (NoMethodError)
Try using it instead of describe for the inside block:
describe BookingsHelper do
it "#booking_price" do
helper.booking_price.should == 'something'
end
end

Resources