5

I'm working on a MVP (minimum viable product). In order to offer a simpler way to secure the admin pages, I just did add http_basic_authenticate_with to my AdminController.

Problem is that when I want to test my AdminController, I get "unauthorized" (401) for not being logged in.

In this scenario, it's irrelevant to test the authentication - it's just temporary, and as soon I go to the next sprint, it's going to removed -, so I'm trying to skip it within RSpec.

Problem is I tried many ways, and none seems to be working.

For example, I tried to modify the http_basic_authenticate_with in order to avoid the authentication. Like this:

require 'spec_helper'

module ActionController
  module HttpAuthentication
    module Basic
      def http_basic_authenticate_with(*args)
      end
    end
  end
end


describe Admin::SubscribersController do  
  describe "GET 'index'" do
    it "should be OK" do 
      get 'index'
      response.should be_successful
    end
  end
end

But when I run it, it still returns "false" for that simple test.

Btw, in order to simplify this test, I just have an empty index action on my AdminController and an empty view (index.html.erb).

4 Answers 4

5

Finally I got it working.

Something as stated in the docs didn't work for me:

get 'index', nil, 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials("admin", "password")

So I tried an "old" approach to do it, which is to set request.env['HTTP_AUTHORIZATION'] :

request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials("admin","password")

None of the other solutions worked, so I will just keep in the meanwhile with this one.

Thanks.

Sign up to request clarification or add additional context in comments.

Comments

4

If it is ok to skip authentication for all tests for a controller, here's the technique I'm using on a current project.

unless Rails.env.test?
  http_basic_authenticate_with name: "slothbear", password: "kuniklo"
end

2 Comments

Hm, now that I've typed that out loud, I think I'd change the condition to if Rails.env.production? I really don't need authentication in the development environment either. Thanks for leading me to greater productivity.
And here's a good recommendation for not using production? as the test: stackoverflow.com/q/8741398/2464
2

In Rails 5.x, this works:

allow(subject).to receive(:authenticate_or_request_with_http_basic)
  .with(anything).and_return true

In Rails 6.x, this works:

allow(subject).to receive(:http_basic_authenticate_or_request_with)
  .with(anything).and_return true

This is because http_basic_authenticate_with is a class-level method that adds a before_action that actually calls one of these two methods under the hood.

You can see which one to use by checking out http_authentication.rb here for Rails 6 or here for Rails 5

Comments

0

You can or even should test authentication. Write test for unauthenticated (it is now) and authenticated. See Testing HTTP Basic Auth in Rails 2.2+ it should help.

7 Comments

Thanks, but in my case (as I said it's just temporary, and probably next week it's going to be removed already) I want to avoid it. Is it possible? Any suggestions on how to skip it?
So maybe you dont need tests at all? But you can do some metaprogramming to avoid it or, which is fastest option - use method in link I found...
I'm sorry, I guess I did express myself a little wrong. The example I gave above was just an example. My real AdminController isn't going to be just that - however, HTTP authentication is temporary. I didn't want to authenticate before my tests because that means when I change the password, I will have to change test too. Thought skip it would be easier and a better approach. If you have an example on how I could skip (the example I gave was the only idea I had), please let me know.
As I said, you need to investigate here: github.com/rails/rails/blob/…, maybe skip_before_filter can help? Or store password in top level constant to avoid changing it in specs.
And on your example above it should be: self << Admin::SubscribersController; def http_basic_authenticate_with(*); end; end
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.