Test des variables d'instance du contrôleur avec rack :: Test et Sinatra
Question
J'ai une application Sinatra qui fournit des pages en lecture seule ou modifiable en fonction de si l'utilisateur est connecté.
Le contrôleur définit une @can_edit
variable qui est utilisée par les vues pour masquer / afficher les liens d'édition. Comment puis-je tester la valeur de @can_edit
dans mes tests? Je ne sais pas comment obtenir à l'instance actuelle du contrôleur sous rack :: Test.
J'utilise class_eval
à bouchonner la méthode logged_in?
dans le contrôleur, mais je vais avoir à recourir à la vérification last_response.body
pour mes liens d'édition pour voir si @can_edit
a été défini ou non.
Comment puis-je tester directement la valeur de @can_edit
?
La solution
Malheureusement, je ne pense pas que cela est possible sans modifier rack :: Test. Lorsque vous faites une demande au cours des essais d'application, Rack :: test effectue les opérations suivantes:
- ajoute la demande à une liste de demandes récentes
- crée une nouvelle instance de votre application et invoque sa méthode
call
- ajoute la réponse de votre application à une liste des réponses récentes
Il est facile d'accéder à la last_request
et last_response
, mais malheureusement, aucune information est enregistrée sur l'état de votre application pendant qu'il est en cours d'exécution.
Si vous êtes intéressé par le piratage ensemble un rack :: patch test pour ce faire, commencez par regarder rack-test/lib/rack/mock_session.rb
en ligne 30. C'est là rack :: test exécute votre application et reçoit les valeurs standard de retour d'application Rack (statut , en-têtes, corps). Je pense que vous allez devoir modifier votre demande ainsi, de recueillir et de rendre accessibles toutes ses variables d'instance.
Dans tous les cas, il est préférable de tester les résultats, pas de détails de mise en œuvre. Si vous voulez vous assurer un lien d'édition n'est pas visible, test pour la présence du lien d'édition par id DOM:
assert last_response.body.match(/<a href="..." id="...">/)
Autres conseils
Il est possible avec un peu de hack. Les cas d'application Sinatra ne sont pas disponibles parce qu'ils sont créés lorsque Sinatra :: Base appel # est appelé. comme expliqué Alex. Ce hack prépare une instance en avant et laisser la prochaine grab appeler.
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
Je compris cette technique raillent l'instance qui exécute le test en cours en premier lieu.
Heres une alternative viable mais méchant
# 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
Cela vous permet de tester contre un avant sinatra instance et filtre ou accès variables créées pour l'application de base.