Testare variabili di istanza di controllo con Rack :: Test e Sinatra
Domanda
Ho un app Sinatra che serve pagine come di sola lettura o modificabili a seconda se l'utente è collegato.
Il controllore imposta un @can_edit
variabile, che viene utilizzato da punti di vista per nascondere / mostrare modificare i collegamenti. Come faccio a testare il valore di @can_edit
nel mio test? Non ho idea di come arrivare alla istanza corrente del controller in rack :: Test.
Io uso class_eval
stub metodo logged_in?
nel controller, ma sto dover ricorrere al controllo last_response.body
per la mia modifica link per vedere se @can_edit
è stata impostata o meno.
Come faccio a verificare il valore di @can_edit
direttamente?
Soluzione
Purtroppo non credo che questo sia possibile senza modificare Rack :: Test. Quando si effettua una richiesta durante il testing delle applicazioni, Rack :: Test esegue le seguenti operazioni:
- aggiunge la richiesta di un elenco di recenti richieste
- crea una nuova istanza dell'applicazione e invoca il suo metodo
call
- aggiunge risposta dell'applicazione ad un elenco di risposte recenti
E 'facile accedere al last_request
e last_response
, ma purtroppo nessuna informazione viene salvata sullo stato della vostra applicazione mentre è in esecuzione.
Se siete interessati a l'hacking insieme una patch rack :: Test per fare questo, iniziare a guardare rack-test/lib/rack/mock_session.rb
on line 30. Questo è dove Rack :: Test esegue l'applicazione e riceve i valori Rack applicazione di ritorno standard di (stato , intestazioni, corpo). La mia ipotesi è che si sta andando ad avere per modificare l'applicazione e, di raccogliere e rendere tutte le sue variabili di istanza accessibile.
In ogni caso, è meglio per testare i risultati, non i dettagli di implementazione. Se si vuole fare in modo un link di modifica non è visibile, test per la presenza del collegamento modifica di DOM ID:
assert last_response.body.match(/<a href="..." id="...">/)
Altri suggerimenti
E 'possibile con un piccolo hack. casi di Sinatra app non sono disponibili perché vengono creati quando Sinatra :: Base # chiamata viene chiamato. come spiegato Alex. Questo mod prepara un'istanza avanti e lasciare che la chiamata successiva afferrarlo.
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
ho capito questa tecnica per deridere l'istanza che gestisce il test in corso in primo luogo.
Ecco una brutta ma valida alternativa
# 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
Questo vi permette di testare contro un Sinatra prima di filtro e o di istanza di accesso variabili create per l'applicazione di base.