2011-07-15 6 views
7

Uso Rails 3 y RSpec 2.6.0.¿Cómo escribir una macro de controlador RSpec que puede aceptar argumentos definidos por let o en un bloque before?

No estoy seguro si eso es posible, pero aquí es lo que me gustaría hacer:

describe UsersController do 
    let(:user) { Fabricate :user } 
    describe "GET /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :get, :show, :id => user.id 
    end 
    describe "PUT /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :put, :update, :id => user.id 
    end 
end 

Me trataron de poner en práctica la macro como esta:

module ControllerMacros 
    def should_return_401_code_if_user_is_not_confirmed(verb, action, params = {}) 
    it "returns a 401 code if the user is not an admin" do 
     send verb, action, params 
     response.code.should == "401" 
    end 
    end 
end 

Pero cuando se ejecuta esas especificaciones que recibo el error undefined local variable or method 'user'. Traté de cambiar a una @ @ variable definida en un bloque anterior, pero tampoco funciona. Sospecho que es porque no estoy en un bloque de ejemplo.

¿Es posible pasar a un controlador los argumentos de macro definidos por let o en un bloque before?

Gracias!

+0

Es posible que desee considerar la refacturación de la prueba. No es una buena idea tener dos condiciones en la prueba: la presencia del 'si' es un olor a prueba. ¿Estás probando si el usuario está confirmado o solo si se devuelve el código apropiado? Si es el último * configure * la confirmación en lugar de verificarlo. –

Respuesta

6

A partir de this thread en la lista de servidores rspec-users, parece que la respuesta es no. El problema es que tus valores de let/before vars no se inicializan hasta el bloque it en el cuerpo de tu macro, por lo que no puedes hacer referencia a ellos como parámetros a la macro llamada.

Estoy tratando de hacer esencialmente lo mismo en un sitio en el que estoy trabajando. La solución que voy a usar es llamar al método macro con un bloque que devolverá el hash de parámetros que desee, y luego usar instance_eval en el cuerpo de la macro para evaluar el bloque usando el alcance de la macro.

#spec 
... 
describe "GET /user/:id" do 
    should_return_401_code_if_user_is_not_confirmed :get, :show { {:id => user.id} } 
end 

#macro 
... 
def should_return_401_code_if_user_is_not_confirmed(verb, action, &params_block) 
    it "returns a 401 code if the user is not an admin" do 
    params = instance_eval &params_block 
    send verb, action, params 
... 
Cuestiones relacionadas