簡體   English   中英

使用Rack :: Test和Sinatra測試控制器實例變量

[英]Testing controller instance variables with Rack::Test and Sinatra

我有一個Sinatra應用程序,它以只讀或可編輯的方式提供頁面,具體取決於用戶是否已登錄。

控制器設置變量@can_edit ,視圖使用該變量來隱藏/顯示編輯鏈接。 如何在測試中測試@can_edit的值? 我不知道如何在Rack :: Test下獲取控制器的當前實例。

我使用class_eval來存根logged_in? 控制器中的方法,但是我不得不求助於檢查last_response.body以獲取我的編輯鏈接,看看是否已經設置了@can_edit

如何直接測試@can_edit的值?

不幸的是,如果不修改Rack :: Test,我認為這是不可能的。 當您在應用程序測試期間提出請求時,Rack :: Test會執行以下操作:

  1. 將請求添加到最近請求列表中
  2. 創建應用程序的新實例並調用其call方法
  3. 將您的應用程序的響應添加到最近的響應列表中

訪問last_requestlast_response很容易,但遺憾的是,在應用程序運行時沒有保存有關應用程序狀態的信息。

如果你有興趣將Rack :: Test補丁一起rack-test/lib/rack/mock_session.rb這里, rack-test/lib/rack/mock_session.rb查看第30行的rack-test/lib/rack/mock_session.rb 。這是Rack :: Test運行你的應用程序並接收標准機架應用程序返回值(狀態,標題,正文)。 我的猜測是,您還必須修改您的應用程序,以收集並使其所有實例變量可訪問。

無論如何,最好測試結果,而不是實現細節。 如果要確保編輯鏈接不可見,請按DOM ID測試是否存在編輯鏈接:

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

有點黑客可能。 Sinatra應用程序的實例不可用,因為它們是在調用Sinatra :: Base#調用時創建的。 正如Alex解釋的那樣 這個hack准備一個實例,讓下一個調用抓住它。

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

我想出了這種技術來模擬首先運行當前測試的實例

這是一個討厭但可行的選擇

# 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

這允許您在過濾之前測試sinatra,或者訪問為基本應用程序創建的實例變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM