Testen Controller Instanzvariablen mit Rack-:: Test und Sinatra
Frage
Ich habe eine Sinatra-Anwendung, die Seiten als schreibgeschützte oder editierbare dient je nachdem, ob der Benutzer angemeldet ist.
Der Controller setzt eine Variable @can_edit
, die von den Ansichten zu hide / show bearbeiten Links verwendet wird. Wie kann ich @can_edit
Wert in meinen Tests testen? Ich habe keine Ahnung, wie in der aktuellen Instanz des Controllers unter Rack bekommen :: Test.
Ich verwende class_eval
die logged_in?
Methode in der Steuerung Stummel, aber ich habe auf die Überprüfung last_response.body
für meine bearbeiten Links greifen, um festzustellen, ob @can_edit
gesetzt wurde oder nicht.
Wie kann ich den Wert von @can_edit
testen direkt?
Lösung
Leider nicht ich denke, das ist möglich, ohne Rack-modifizierende :: Tests. Wenn Sie eine Anforderung bei Anwendungstests machen, Schärfen :: Test macht folgendes:
- fügt die Anforderung an eine Liste der letzten Anfragen
- erstellt eine neue Instanz der Anwendung und ruft seine
call
Methode - fügt Ihre Anwendung Antwort auf eine Liste der letzten Antworten
Es ist einfach, den Zugang der last_request
und last_response
, aber leider keine Informationen über den Zustand Ihrer Anwendung gespeichert, während es läuft.
Wenn Sie in Hacking zusammen ein Rack-interessiert sind :: Test-Patch, dies zu tun, starten Sie durch in rack-test/lib/rack/mock_session.rb
auf Linie 30. Diese Suche ist, wo Rack-:: Testen Sie Ihre Anwendung läuft und erhält die Standard-Rack-App Rückgabewerte (Status , Überschriften, Körper). Meine Vermutung ist, dass Sie gehen, um Ihre Anwendung zu haben, zu modifizieren und zu sammeln und zugänglich alle seine Instanzvariablen zu machen.
In jedem Fall ist es am besten Test für Ergebnisse, nicht Implementierungsdetails. Wenn Sie sicher, dass ein Link Bearbeiten nicht sichtbar machen wollen ist, Test für das Vorhandensein des Link Bearbeiten von DOM-ID:
assert last_response.body.match(/<a href="..." id="...">/)
Andere Tipps
Es ist möglich, mit einem kleinen Hack. Sinatra App-Instanzen sind nicht verfügbar, da sie erstellt werden, wenn Sinatra :: Base # Aufruf aufgerufen wird. wie Alex erklärt. Dieser Hack bereitet eine Instanz voraus und lassen Sie die nächsten Anruf greift es.
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
dachte ich diese Technik, um Mock die Instanz, die den aktuellen Test in erster Linie ausgeführt wird.
Heres eine unangenehme, aber praktikable Alternative
# 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
Auf diese Weise können Sie gegen einen sinatra testen, bevor Filter und oder Zugriffsinstanzvariablen für die Basisanwendung erstellt.