Integration Testing - omniauth/omniauth GitHub Wiki
OmniAuth has some facilities for mocking its authentication flow when you are performing integration tests. Here's how it works.
OmniAuth.config.test_mode
You can turn on "test mode" for OmniAuth like so:
OmniAuth.config.test_mode = true
Once you have enabled test mode, all requests to OmniAuth will be short circuited to use the mock authentication hash as described below. A request to /auth/provider
will redirect immediately to /auth/provider/callback
.
Note: For ActionDispatch::IntegrationTest
, make sure you also call follow_redirect!
after /auth/provider
otherwise redirect to /auth/provider/callback
won't happen.
OmniAuth.config.mock_auth
The mock_auth
configuration allows you to set per-provider (or default) authentication hashes to return during integration testing. You can set it like so:
OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new({
:provider => 'twitter',
:uid => '123545'
# etc.
})
You can set the :default
key to return a hash for providers that haven't been specified. Once you set the mock auth hash and turn on test mode, all requests to OmniAuth will return an auth hash from the mock.
Check out faker-omniauth for an easy way to generate mock data.
OmniAuth.config.add_mock
You can also use the shortcut #add_mock
method to quickly add a new mock provider. This information will automatically be merged with the default info so it will be a valid response.
OmniAuth.config.add_mock(:twitter, {:uid => '12345'})
Mocking Failure
If you set a provider's mock to a symbol instead of a hash, it will fail with that message.
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials
You will be redirected back to /auth/failure?message=invalid_credentials.
By default Omniauth will raise an exception for invalid credentials in the development and test environments. If you'd like to be redirected to the /auth/failure
endpoint in those environments, include this code:
OmniAuth.config.on_failure = Proc.new { |env|
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}
Cleanup
In between tests, you probably want to reset OmniAuth to a consistent state. In your test-suite-wide configuration (e.g. in setup
or before(:each)
), run
OmniAuth.config.mock_auth[:twitter] = nil
Setting up the controller
When testing the OmniAuth, you need to set two environment variables, see the sample below using RSpec and Twitter OmniAuth:
before do
request.env["devise.mapping"] = Devise.mappings[:user] # If using Devise
request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter]
end
Or when using request specs with newer versions of RSpec, which do not allow access to the request object:
before do
Rails.application.env_config["devise.mapping"] = Devise.mappings[:user] # If using Devise
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter]
end
This prevents the route error, see the sample below
Failure/Error: get :twitter
AbstractController::ActionNotFound:
Could not find devise mapping for path "/users/auth/twitter/callback".
Maybe you forgot to wrap your route inside the scope block? For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end