2009-12-18 11 views
8

Tengo una aplicación que sirve Sinatra páginas como de sólo lectura o modificable en función de si el usuario está conectado.variables de instancia del controlador de pruebas con el estante :: Prueba y Sinatra

El controlador establece una variable @can_edit, que es utilizado por las vistas para ocultar/mostrar enlaces de edición. ¿Cómo puedo probar el valor @can_edit en mis pruebas? No tengo idea de cómo llegar a la instancia actual del controlador en Rack :: Test.

utilizo class_eval al stub del método logged_in? en el controlador, pero estoy teniendo que recurrir a la comprobación last_response.body para mis editar enlaces para ver si @can_edit se ha establecido o no.

¿Cómo puedo probar el valor de @can_edit directamente?

Respuesta

8

Lamentablemente, no creo que esto sea posible sin modificar Rack :: Test. Cuando se hace una solicitud durante las pruebas de aplicaciones, Cambio :: prueba consiste en lo siguiente:

  1. añade la solicitud a una lista de peticiones recientes
  2. crea una nueva instancia de la aplicación e invoca su método call
  3. agrega la respuesta de su aplicación a una lista de respuestas recientes

es fácil acceder al last_request y last_response, pero por desgracia no se guardará información sobre el estado de su solicitud, mientras que es Runni ng.

Si está interesado en hackear un parche Rack :: Test para hacer esto, comience por mirar rack-test/lib/rack/mock_session.rb en la línea 30. Aquí es donde Rack :: Test ejecuta su aplicación y recibe los valores de retorno de la aplicación Rack estándar (estado, encabezados, cuerpo). Supongo que tendrá que modificar su aplicación también, para recopilar y hacer accesibles todas sus variables de instancia.

En cualquier caso, es mejor probar los resultados, no los detalles de implementación. Si desea asegurarse de que un enlace de edición no es visible, la prueba de la presencia del enlace de edición de DOM id:

assert last_response.body.match(/<a href="..." id="...">/) 
+0

"es mejor probar los resultados, no los detalles de implementación" He visto declaraciones similares como esta antes, y tengo que estar en desacuerdo. Si quiere 2, 1 + 1 funciona bastante bien, pero también lo hace 1 + 2 + 10 - 11. Ninguno de los dos significa que su aplicación "realmente está funcionando correctamente". – nowk

+1

No estoy completamente en desacuerdo con usted, sin embargo: digamos que hay un método que se implementa incorrectamente.Si el método devuelve la respuesta correcta el 100% del tiempo (no se puede pensar en un caso en el que falla), ¿la implementación es realmente "incorrecta"? ¿Importa? Si se encuentra probando los valores de las variables dentro de los métodos, es posible que no tenga suficientes casos de prueba (entradas). Si cambia el nombre de las variables o cambia la implementación de su aplicación sin cambiar su comportamiento, sus pruebas deberían pasar sin modificaciones. Esta es una gran razón para usar las pruebas en primer lugar. –

+0

Creo que la prueba @can_edit está probando la salida del controlador. No me gusta probarlo indirectamente al verificar la vista de lo que debería suceder cuando se establece @can_edit. Esa debe ser una prueba diferente, únicamente para la vista. – Brian

4

Es posible con un pequeño truco. Las instancias de la aplicación Sinatra no están disponibles porque se crean cuando se llama a la llamada Sinatra :: Base #. como Alex explicó. Este truco prepara una instancia adelante y deja que la próxima llamada la atrape.

require 'something/to/be/required' 

class Sinatra::Base 
    @@prepared = nil 

    def self.onion_core 
    onion = prototype 
    loop do 
     onion = onion.instance_variable_get('@app') 
     return onion if onion.class == self || onion.nil? 
    end 
    end 

    def self.prepare_instance 
    @@prepared = onion_core 
    end 

    # Override 
    def call(env) 
    d = @@prepared || dup 
    @@prepared = nil 
    d.call!(env) 
    end 
end 

describe 'An Sinatra app' do 
    include Rack::Test::Methods 

    def app 
    Sinatra::Application 
    end 

    it 'prepares an app instance on ahead' do 
    app_instance = app.prepare_instance  
    get '/foo' 
    app_instance.instance_variable_get('@can_edit').should be_true 
    end 
end 

me di cuenta de esta técnica para mock the instance that runs the current test en el primer lugar.

+0

Esto devuelve nil application_instance para mí. Probablemente el último Sinatra cambió su clase base. – gpavlidi

0

Heres una alternativa viable desagradable pero

# app.rb - sets an instance variable for all routes 
before do 
    @foo = 'bar' 
end 

# spec.rb 
it 'sets an instance variable via before filter' do 
    my_app = MySinatraApplication 
    expected_value = nil 
    # define a fake route 
    my_app.get '/before-filter-test' do 
    # as previously stated, Sinatra app instance isn't avaiable until #call is performed 
    expected_value = @foo 
    end 
    my_app.new.call({ 
    'REQUEST_METHOD' => 'GET', 
    'PATH_INFO' => '/before-filter-test', 
    'rack.input' => StringIO.new 
    }) 
    expect(expected_value).to eq('bar') 
end 

Esto le permite probar contra un Sinatra antes de variables de filtro y de instancia o de acceso creado para la aplicación de base.

Cuestiones relacionadas