I have this code
require_relative 'die'
describe Die do
describe '#initialize' do
it 'expects a single argument' do
expect(Die.instance_method(:initialize).arity).to eq 1
end
it 'raises ArgumentError if sides are < 1' do
expect { #####line 10
Die.new(-1)
}.to raise_error(ArgumentError)
expect {
Die.new(0)
}.to raise_error(ArgumentError)
end
end
I am getting the following error
> Die#initialize raises ArgumentError if sides are < 1
Failure/Error: expect {
expected ArgumentError but nothing was raised
# ./spec.rb:10:in `block (3 levels) in <top (required)>'
I have marked line 10.Any help how I can remove this error?
and this is my DIE class
class Die
def initialize(sides)
end
def num_of_sides()
end
def roll()
end
end
Put this line inside your initialize method:
raise ArgumentError if sides < 1
Related
I have to test a code where I am raising some errors, I tried several techniques but it failed. The structure of the class is defined below:
SchemaController:
class SchemasController < ApplicationController
def index
#get_schema = Api::AnalyticsQueryBuilderMetadataService::Schema.show
end
end
Show method under Api -> AnalyticsQueryBuilderMetadataService -> Schema.rb file:
def self.show
params = { 'limit' => 40 }
response = Api::Connection.initiate_request('entities', params)
if response.nil?
Rails.logger.error 'Data not found for ClientId '
raise 'Data not found'
else
get_schema(response)
end
end
Rspec test I wrote for schema_spec.rb:
require 'rails_helper'
require 'spec_helper'
RSpec.describe Api::AnalyticsQueryBuilderMetadataService::Schema do
describe 'GET all schema' do
before do
# allow_any_instance_of(SchemasController).to receive(:connection).and_return({})
#binding.pry
allow(Api::Connection).to receive(:initiate_request).and_return(nil)
end
context 'When no json body is passed' do
it 'Raises NoMethodError' do
# obj = SchemasController.new
result = Api::AnalyticsQueryBuilderMetadataService::Schema.show()
# expect {result}.to raise_error(RuntimeError)
expect{result}.to raise_error
end
end
end
end
But It is giving error as:
Failures:
1) Api::AnalyticsQueryBuilderMetadataService::Schema GET all schema When no json body is passed Raises NoMethodError
Failure/Error: raise 'Data not found'
RuntimeError:
Data not found
# ./app/lib/api/analytics_query_builder_metadata_service/schema.rb:22:in `show'
# ./spec/lib/api/analytics_query_builder_metadata_service/schema_spec.rb:17:in `block (4 levels) in <top (required)>'
Finished in 2.3 seconds (files took 5.63 seconds to load)
44 examples, 1 failure
Failed examples:
rspec ./spec/lib/api/analytics_query_builder_metadata_service/schema_spec.rb:15 # Api::AnalyticsQueryBuilderMetadataService::Schema GET all schema When no json body is passed Raises NoMethodError
Help me to solve this.
From the docs;
Use the raise_error matcher to specify that a block of code raises an
error.
It means that the code in the block should be the one raising the error, but in your case the error is being raised when you declare the result variable.
To make it work you can skip the variable declaration and pass the variable value as the expect block;
expect { Api::AnalyticsQueryBuilderMetadataService::Schema.show }
.to raise_error(StandardError, 'Data not found')
I would have expected the following code to work but the definition of class Error causes too many end statements as per test result
class MenuItem < ApplicationRecord
has_one :page, dependent: :destroy
has_ancestry
validates :menu_text, uniqueness: true, presence: true
accepts_nested_attributes_for :page
before_save :generate_url, :validate_home_page
after_destroy :ensure_home_page_remains
Class Error < StandardError
end
def to_param
url # or "#{id}-#{name}".parameterize
end
#Home page is a special case and must always exist
#To be called by migration on deploy but must not be editable.
#Only the page content should be editable
def self.create_home_page
mi = self.find_by_url("home")
if mi.blank?
mi = self.new
mi.menu_text = "Home"
mi.url_editable = false
pg = mi.build_page
pg.content = "<h1>Home</h1>"
mi.save
end
end
protected
def validate_home_page
if changed?
if menu_text.changed? && menu_text_was == "Home"
errors.add(:menu_text, "Can't change home page menu text")
end
end
end
def ensure_home_page_remains
if menu_text == "Home"
raise Error.new "Can't delete home page"
end
end
def generate_url
self.url = menu_text.parameterize
end
end
The rspec model test results in
An error occurred while loading ./spec/models/menu_item_spec.rb.
Failure/Error:
RSpec.describe MenuItem, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
SyntaxError:
/home/jamie/Development/rails/comtech/rawdoncc/app/models/menu_item.rb:54: syntax error, unexpected end, expecting end-of-input
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/zeitwerk-2.3.0/lib/zeitwerk/kernel.rb:16:in `require'
# ./spec/models/menu_item_spec.rb:3:in `<main>'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
# /home/jamie/.rvm/gems/ruby-2.6.3#rawdon/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
Finished in 0.00003 seconds (files took 1 second to load)
0 examples, 0 failures, 1 error occurred outside of examples
[1] guard(main)>
It's a pending test and has not been written yet but just to prove the point this is not a test code issue the console ouput raises the same error
Loading development environment (Rails 6.0.2.2)
irb: warn: can't alias context from irb_context.
2.6.3 :001 > mi = MenuItem.new
Traceback (most recent call last):
1: from (irb):1
SyntaxError (/home/jamie/Development/rails/comtech/rawdoncc/app/models/menu_item.rb:54: syntax error, unexpected end, expecting end-of-input)
2.6.3 :002 >
I feel I must be missing something very basic but can't for the life of me spot it and no, it's not a case of removing the end statement from the Error class declaration
I am totally dumbfounded with this and would welcome alternative suggestions as to how to do this reliably
I think is the class definition inside:
Class Error < StandardError
end
Should be
class Error < StandardError
end
I hope this helps.
Because of rubocop error I want to avoid using allow_any_instance_of in my specs.
I'm trying to change this one:
before do
allow_any_instance_of(ApplicationController).to receive(:maintenance_mode_active?).and_return(false)
end
it 'returns http success' do
expect(response).to have_http_status(:success)
end
According to the rubocop-docs it should be like:
let(:maintenance_mode?) { instance_double(ApplicationController) }
before do
allow(ApplicationController).to receive(:maintenance_mode_active?).and_return(false)
allow(maintenance_mode?).to receive(:maintenance_mode_active?)
end
it 'returns http success' do
expect(response).to have_http_status(:success)
end
Class which I want to test:
private
def check_maintenance?
if maintenance_mode_active? == true
redirect_to maintenance_mode
elsif request.fullpath.include?(maintenance_mode_path)
redirect_to :root
end
end
def maintenance_mode_active?
# do sth ...
mode.active?
end
With code above I've got an error:
2.1) Failure/Error: allow(ApplicationController).to receive(maintenance_mode?).and_return(false)
#<InstanceDouble(ApplicationController) (anonymous)> received unexpected message :to_sym with (no args)
# ./spec/controllers/static_pages_controller_spec.rb:15:in `block (4 levels) in <top (required)>'
2.2) Failure/Error: allow(ApplicationController).to receive(maintenance_mode?).and_return(false)
TypeError:
[#<RSpec::Mocks::MockExpectationError: #<InstanceDouble(ApplicationController) (anonymous)> received unexpected message :to_sym with (no args)>] is not a symbol nor a string
# ./spec/controllers/static_pages_controller_spec.rb:15:in `block (4 levels) in <top (required)>'
You must stub ApplicationController to return the instance_double(ApplicationController):
let(:application_controller) { instance_double(ApplicationController) }
allow(ApplicationController).to receive(:new).and_return(application_controller)
allow(application_controller).to receive(:maintenance_mode_active?).and_return(false)
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.
I can't figure out why this RSpec test fails. Any advice? I'm new-ish to FactoryGirl, RSpec, and TDD in general.
Controller:
def update
#vendor = current_user.vendors.find(params[:id])
if #vendor.update_attributes(params[:vendor])
redirect_to vendor_path(#vendor)
else
render 'edit'
end
end
Test:
require 'spec_helper'
describe VendorsController do
login_user
before :each do
#user = subject.current_user
#vendor = FactoryGirl.create(:vendor, :user => #user)
end
[...]
describe 'POST update' do
def do_update
post :update, :id => #vendor.id, :vendor => FactoryGirl.attributes_for(:vendor)
end
[...]
it 'should update a given vendor' do
do_update
#vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
end
end
end
Factory:
FactoryGirl.define do
factory :vendor do
name 'Widget Vendor'
user
end
end
The Failure:
Failures:
1) VendorsController POST update should update a given vendor
Failure/Error: #vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
(#<Vendor:0x007faeb75e77d0>).update_attributes({:name=>"Widget Vendor"})
expected: 1 time
received: 0 times
# ./spec/controllers/vendors_controller_spec.rb:108:in `block (3 levels) in <top (required)>'
Update:
I'm a little closer, now. I changed the test to the following:
it 'should update a given vendor' do
Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
do_update
end
And the new error is:
Failures:
1) VendorsController POST update should update a given vendor
Failure/Error: post :update, :id => #vendor.id, :vendor => FactoryGirl.attributes_for(:vendor)
#<Vendor:0x007ff30d765900> received :update_attributes with unexpected arguments
expected: ({:name=>"Widget Vendor"})
got: ({"name"=>"Widget Vendor"})
# ./app/controllers/vendors_controller.rb:33:in `update'
# ./spec/controllers/vendors_controller_spec.rb:98:in `do_update'
# ./spec/controllers/vendors_controller_spec.rb:108:in `block (3 levels) in <top (required)>'
Answer...?
Well, this worked. There has to be a better way of doing this, though:
Vendor.any_instance.should_receive(:update_attributes).with(JSON.parse(FactoryGirl.attributes_for(:vendor).to_json)).and_return(true)
I think you are doing it wrong.
The #vendor object in specs is another one that in your controller, so it doesn't receive "update_attributes" method.
You can try this (rspec 2.5+ probably):
Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
Or you can check if object attributes has changed:
expect{
do_update
}.to change(...)
I believe you need to set your expectations before posting the request; otherwise, by the time it hits your expectation the object has already been set. So move do_update after your should_receive line:
it 'should update a given vendor' do
#vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
do_update
end
You can use the Hash stringify keys method in rails:
Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor).stringify_keys)