Rack::Test と Sinatra を使用したコントローラーのインスタンス変数のテスト

StackOverflow https://stackoverflow.com/questions/1928968

  •  20-09-2019
  •  | 
  •  

質問

ユーザーがログインしているかどうかに応じて、ページを読み取り専用または編集可能として提供する 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_request そして last_response, ただし、残念ながら、アプリケーションの実行中の状態に関する情報は保存されません。

これを行うために Rack::Test パッチをハッキングすることに興味がある場合は、まず以下を見てください。 rack-test/lib/rack/mock_session.rb 30行目。ここで、Rack::Test はアプリケーションを実行し、標準の Rack アプリの戻り値 (ステータス、ヘッダー、本文) を受け取ります。私の推測では、すべてのインスタンス変数を収集してアクセスできるようにするには、アプリケーションも変更する必要があると思います。

いずれの場合も、実装の詳細ではなく、結果をテストすることが最善です。編集リンクが表示されていないことを確認したい場合は、DOM ID で編集リンクの存在をテストします。

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

他のヒント

これは少しハックで可能です。シナトラ::ベース#コールが呼び出されたときにそれらが作成されるため、シナトラアプリのインスタンスは使用できません。アレックスは説明したように。このハックは先に、インスタンスを作成し、次の呼び出しは、それをつかむせます。

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

これはフィルタの前シナトラに対してテストおよびまたはベースアプリケーション用に作成されたインスタンス変数にアクセスすることができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top