my controller is something like :
before_filter: check_login_status
def check_login_status
send_response(:not_logged_in) unless user.logged_in?
end
my spec for this is as :
it 'returns error unless user is not logged in' do
expect(controller).to receive(:send_response).with(:not_logged_in)
controller.send(:check_login_status)
end
now i want to write another test as :
it 'checks the login status of user before any action' do
.......
end
how can i complete the second test ?
CodePudding user response:
You don't test callbacks - you test behavior.
Callbacks are an internal implementation detail of a controller and are implemented as private methods (or at least should be if you're doing it right). You should test the behavior of the application and not how it gets the job done.
For testing a authentication you want to write a request spec where you send a real HTTP request to the endpoint and write expections about:
- Is the correct status code returned?
- Is the user redirected?
- Are there any side effects happening that should not be happening? For example records being created, destroyed or updated.
- Is the user getting any information they should not be getting?
An example:
require 'spec_helper'
RSpec.describe "Things", type: :request do
describe "POST /things" do
context "when not logged in" do
let(:action) do
post '/things', params: { thing: { foo: 'bar' }}
end
it "does not allow a thing to be created" do
expect{ action }.to_not change(Thing, :count)
end
it "redirects the user to the login page" do
action
expect(response).to redirect_to '/login'
end
# etc
end
end
end
This kind of testing can be somewhat repitive and tedious - shared examples can help with that.
Alternatively you can do the authentication system right so that it actually raises an exception that you can test is being raised by disabling rescue_from. The fact that you're tempted to poke inside could actually be revealing a design smell.
