2012-02-05 15 views
7

Estoy creando un proveedor OAuth de 2 patas para mi API. Todo está conectado correctamente y puedo hacer llamadas firmadas desde la consola de rieles. El problema que tengo es que tengo problemas para integrar OAuth en el controller_spec.Cómo puedo decirle a las especificaciones del controlador que utilicen la solicitud firmada de OAuth

Aquí es un ejemplo de una llamada de trabajo en mi servidor:

coneybeare $ rails c test 
Loading test environment (Rails 3.2.0) 
rails test: main 
>> consumer = OAuth::Consumer.new("one_key", "MyString", :site => [REDACTED]) 
# => #<OAuth::Consumer:0x007f9d01252268 @key="one_key", @secret="MyString", @options={:signature_method=>"HMAC-SHA1", :request_token_path=>"/oauth/request_token", :authorize_path=>"/oauth/authorize", :access_token_path=>"/oauth/access_token", :proxy=>nil, :scheme=>:header, :http_method=>:post, :oauth_version=>"1.0", :site=>[REDACTED]}> 

ruby: main 
>> req = consumer.create_signed_request(:get, "/api/v1/client_applications.json", nil) 
# => #<Net::HTTP::Get GET> 

ruby: main 
>> res = Net::HTTP.start([REDACTED]) {|http| http.request(req) } 
# => #<Net::HTTPOK 200 OK readbody=true> 

ruby: main 
>> puts res.body 
{"client_applications":[{"id":119059960,"name":"FooBar1","url":"http://test1.com"},{"id":504489040,"name":"FooBar2","url":"http://test2.com"}]} 
# => nil 

y aquí es lo que estoy haciendo en mis pruebas del controlador:

require 'oauth/client/action_controller_request' 
describe Api::ClientApplicationsController do 
    include OAuthControllerSpecHelper 
    … 
    … 
    it "assigns all client_applications as @client_applications" do 
     consumer = OAuth::Consumer.new("one_key", "MyString", :site => [REDACTED]) 
     ActionController::TestRequest.use_oauth=true 
     @request.configure_oauth(consumer) 
     @request.apply_oauth! 
     puts "request.env['Authorization'] = #{@request.env['Authorization']}" 
     get :index, {:api_version => 'v1', :format => :json} 
     response.should be_success # Just this for now until I can get authorization, then proper controller testing 
    end 
end 

La salida de la prueba:

request.env['Authorization'] = OAuth oauth_consumer_key="one_key", oauth_nonce="gzAbvBSWyFtIYKfuokMAdu6VnH39EHeXvebbH2qUtE", oauth_signature="juBkJo5K0WLu9mYqHVC3Ar%2FATUs%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1328474800", oauth_version="1.0" 
1) Api::ClientApplicationsController GET index assigns all client_applications as @client_applications 
    Failure/Error: response.should be_success 
    expected success? to return true, got false 

Y la llamada al servidor correspondiente desde el registro de rieles:

Processing by Api::ClientApplicationsController#index as JSON 
    Parameters: {"api_version"=>1} 
    Rendered text template (0.0ms) 
Filter chain halted as #<OAuth::Controllers::ApplicationControllerMethods::Filter:0x007f85a51a8858 @options={:interactive=>false, :strategies=>:two_legged}, @strategies=[:two_legged]> rendered or redirected 
Completed 401 Unauthorized in 15ms (Views: 14.1ms | ActiveRecord: 0.0ms) 
    (0.2ms) ROLLBACK 

No puedo entender por qué no funciona:/¿Estoy cometiendo un error obvio?

+0

suena como que no es realmente un controlador especulación. ¿Lo intentó como una especificación de solicitud? – apneadiving

+0

Es una especificación de controlador. El ejemplo fue reducido a sus elementos esenciales. Si está en lo cierto, y este tipo de prueba debe entrar en la especificación de la solicitud, ¿de qué otro modo se supone que debo probar mi controlador cuando lo tengo protegido por OAuth? – coneybeare

+0

Estoy probando una API en estos días y en las especificaciones del controlador, simplemente paso los valores correctos en el encabezado. Lo siento, realmente no lo sé por OAuth. Lo que temo en su caso es que 'create_signed_request' no obtiene el resultado esperado. ¿Intentó depurarlo? Solo estoy pensando: puede omitir algunos 'before_filters' mientras prueba – apneadiving

Respuesta

0

Resulta que la mejor manera de probar mi controlador fue la más simple también. En lugar de intentar firmar cada prueba para que el controlador obtenga la información correcta (algo que de hecho pertenece a una especificación de solicitud, no a una especificación de controlador), descubrí que podía darle al controlador la información que necesitaba de forma manual.

Para ello, simplemente tenía que stub 2 métodos:

fixtures :client_applications 
before(:each) do 
    @client_application1 = client_applications(:client_application1) 
    Api::ClientApplicationsController::Authenticator.any_instance.stub(:allow?).and_return(true) 
    controller.stub(:client_application).and_return(@client_application1) 
end 

Stubbing el método de autenticación allow? causó la rejilla para que se engañe pensando que fue autenticado. allow? también estableció el client_application basado en las credenciales, así que también tuve que colgarlo. Ahora que la autenticación está fuera del camino, puedo probar mi controlador correctamente.

0

Eche un vistazo a cómo funcionan los ayudantes de prueba de Omniauth, específicamente estos archivos: https://github.com/intridea/omniauth/tree/master/lib/omniauth/test. Consulte su wiki page on integration testing para obtener ideas sobre cómo se configura esto. Me doy cuenta de que estás creando un proveedor, no un cliente, pero este puede ser un buen punto de partida. Además, como algunos de los comentaristas ya han dicho, no sé si puede hacer esto con una prueba de controlador; Es posible que necesite una solicitud o prueba de integración para simular completamente el entorno del rack.

1

Si desea probarlo en una especificación de petición y de hecho necesita probar sin tropezar, se puede construir un consumidor de OAuth y firmar una petición como esta:

@access_token = FactoryGirl.create :access_token 
    @consumer = OAuth::Consumer.new(@access_token.app.key, @access_token.app.secret, :site => "http://www.example.com/") 
    @path = "/path/to/request" 
    @request = @consumer.create_signed_request(:get, @path, OAuth::AccessToken.new(@consumer, @access_token.token, @access_token.secret)) 
    get @path, nil, { 'HTTP_AUTHORIZATION' => @request.get_fields('authorization').first } 
Cuestiones relacionadas