Test for ActiveRecord::RecordNotFound
Look in documentation for rspec-expectations#expecting-errors
this:
expect(VerseSelector.select_intro_verse).to raise_exception
should be except
syntax for exception must be lambda
or proc
:
expect { VerseSelector.select_intro_verse }.to raise_exception(ActiveRecord::RecordNotFound)
ActiveRecord::RecordNotFound rspec how to test
Assuming you are not rescuing ActiveRecord::RecordNotFound
from somewhere in your controller(s), then this code will raise the error, and return a status code 404
.
If you are trying to test that the exception will be raised, you need to use the matcher expect { <block_of_code> }.to raise_error <error_class>
If an exception should not be raised, then check your exception handler, because it is not being invoked.
If you want to do this without raising an ActiveRecord::RecordNotFound
, you will need to switch find(id)
with where(id: id).first
How to expect raise ActiveRecord::RecordNotFound rspec?
First its probably a good idea to explain that the exception matchers will only actually match uncaught exceptions. Thats because its basically just a rescue statement and rescues the exception as it bubbles up the call stack and its intended to test that a peice of code raises an exception which its up to the consumer to catch - that is an example of testing the behavior.
Testing that code raises and rescues a exception on the other hand is testing how it does its job.
def foo
raise SomeKindOfError
end
def bar
begin
raise SomeKindOfError
rescue SomeKindOfError
puts "RSpec will never catch me!"
end
end
describe "#foo" do
it "raises an exception" do
expect { foo }.to raise_exception(SomeKindOfError)
end
end
describe "#bar" do
it "rescues the exception" do
expect { bar }.to_not raise_exception(SomeKindOfError)
end
end
When you use rescue_from
its basically just syntactic sugar for using an around_action callback to rescue the given exception:
class ApplicationController
around_action :handle_errors
private
def handle_errors
begin
yield
rescue SomeKindOfError
do_something
end
end
end
While RSpec did at one point have bypass_rescue
for controller specs the use of controller specs is greatly discouraged by both the Rails and RSpec teams and you're really just testing the implementation instead of the behavior.
Instead you should test what the actual controller does instead of how it does it.
context 'invalid confirmation_token' do
# explicit use of subject is a code smell
before do
post signup_step5_path,
params: {
user: {
password: 'hoge',
password_confirmation: 'hoge',
confirmation_token: 'wrong_token'
}
}
end
let(:user) { User.find_by(confirmation_token: 'testtesttest') }
it 'does not update the users password' do
expect(user.valid_password?('hoge')).to be_falsy
end
it 'returns a 404 - NOT FOUND' do
expect(response).to have_http_status(:not_found)
end
# using Capybara in a feature spec is a better way to do this.
it 'renders something' do
expect(response.body).to match("Oh Noes!")
end
end
Rspec: How to verify if a record has been deleted?
You have two choices. You can test that
a record was removed from the database
it "removes a record from the database" do
expect { person.destroy }.to change { Person.count }.by(-1)
endbut that doesn't tell you which record was removed.
Or that the exact record does not exist in the database anymore
it "removes the record from the database" do
person.destroy
expect { person.reload }.to raise_error(ActiveRecord::RecordNotFound)
endor
it "removes the record from the database" do
person.destroy
expect(Person.exists?(person.id)).to be false
endBut that does not make sure that the record existed before.
A combination of both could be:
it "removes a record from the database" do
expect { person.destroy }.to change { Person.count }.by(-1)
expect { person.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
RSpec ActiveRecord::RecordNotFound
In your request, you're doing post :create, { appointment: { dentist_id: '1', ... } }
, which means that params[:dentist_id]
in your controller will be nil
(notice how you're nesting dentist_id
under appointment
in your request params). To fix this, change @dentist = Dentist.find(params[:dentist_id])
in your controller action to @dentist = Dentist.find(params[:appointment][:dentist_id])
, or change your request to post :create, { dentist_id: '1', appointment: { patient_id: '2' ... } }
.
Update
You'll also need to create a Dentist
record in your database before the test is run. To do that, add something like this to your test case:
describe 'POST #create' do
before { Dentist.create!(id: 1) }
it 'assigns a newly created appointment as @appointment' do
post :create, { dentist_id: '1', appointment: { patient_id: '2', appt_date: '2015-12-05 09:00:00' } }
...
end
end
Related Topics
Ruby Instance Method & Conditional Local Variable Assignment with Same Name
Check If String Is Repetition of an Unknown Substring
Cannot Install Ruby 1.9.3 on a Clean Lion Install
Attr_Accessor, Not Able to Access Property
Mongomapper Many to Many Issue with Array
Ruby: Unexpected End-Of-Input, Expecting Keyword_End for If Statement
Emulating Int64 Overflows in Ruby
Mail_Form Gem with Sidekiq Worker
How to Create This File Input and Output Assignment in Ruby
Ruby - How to Retrieve Sum in Array Group by Multiple Keys with Condition Max
Ruby Executable Won't Start on Win10 and Win7
Adding Nested Attributes to Devise User Model
Sorting of 2D Array by Its Amount of in the Inner Elements
Ruby, MAC, Geektool Question, File Access Rights
Consolidating Duplicate Array Items
When Joining Table, Rails Anyway Makes Additional Request When Accessing Fields from Joined Table