testing custom devise and/or warden strategy with rspec
-
24-02-2021 - |
Question
I see plenty that lead to custom authorization strategies for devise and warden, but what I'm sepcifically after is testing these solutions with rspec. Similar to this question: Filtering users who are able to sign in with Devise
What can I do to test this sort of implementation. Rails 3.1.1, Devise (most current), etc.
Solution
For those that may do this in the future, here is my solution:
This is the class that sets a new strategy for authentication through Devise (and it could also be used with Warden with a few small changes).
require 'devise/strategies/authenticatable'
module Devise
module Strategies
class AndroidAuthenticatable < Authenticatable
def valid?
# return true/false
return valid_params? && valid_headers?
end
def authenticate!
failure_message = "Authentication failed for device/user"
klass = mapping.to # if we're going to come here, we can mock this
begin
# code to determine whether or not to authenticate this request
# if yes, success!(instance of klass)
# if no, fail!(messsage)
rescue
fail!(failure_message) # always fail if not success
end
end
protected
def valid_params?
# params that show whether request should be here
end
def valid_headers?
# headers that determine if request should be here
end
end
end
end
The previous class is in my lib/.../strategies directory. I also have lib configured for auto-loading through the rails configuration.
From the rspec side, after I created the above class I write out a few stubs/mocks. Here is a basic rspec file to get you started.
# I do this in before block or right before test executes
@request = mock(:request)
@strategy = Devise::Strategies::AndroidAuthenticatable.new(nil)
@request.should_receive(:headers).and_return({#hash of the headers you are testing})
@strategy.should_receive(:params).at_least(:once).and_return({#hash of the params})
@strategy.should_receive(:request).and_return(@request)
# Break these up as needed to test failing and successful
# strategies for your application
lambda {
@strategy.should be_valid
@strategy.authenticate!.should eql :success
}.should_not raise_error
This isn't all inclusive, but I feel it should get us a good head start when adding strategies with Warden or Devise. I actually had to implement what I thought would work and then right tests to prove it after the fact. Now we can do it the other way around perhaps.