Test authorization logic in Rails
23 April 2022 (Updated 29 April 2022)
Suppose you decide to implement authorization checks using a gem like Pundit. Pundit provides a nice DSL for writing policy specs, but it’s possible that even though you’ve written correct authorization policies, you forget to call them in your controller actions.
Pundit offers a built-in way of avoiding this mistake, but I personally find that method a little quirky and confusing. Instead, I prefer to include authorization checks as part of my feature tests. Something like this:
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Delete note', type: :feature do
it "only the note's owner can delete the note", type: :request do
jim, bob = create_pair(:user)
bob_note = create(:note, user: bob)
login_as(jim)
expect { delete note_path(bob_note) }.to raise_unauthorized_error
end
end
I like to use a raise_unauthorized_error
custom RSpec matcher to improve code readability:
RSpec::Matchers.define :raise_unauthorized_error do
match do |given_proc|
begin
given_proc.call
rescue Pundit::NotAuthorizedError
return true
end
false
end
supports_block_expectations
failure_message do
'expected Pundit::NotAuthorizedError but nothing was raised'
end
end
Tagged:
Rails testing
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment