13

Sinatraアプリケーションへの util メソッドがあり、 TestCase.

問題は、それを呼び出す方法がわからないことです。使用しただけでapp.util_methodはエラーが発生しますNameError: undefined local variable or method 'util_method' for #<Sinatra::ExtendedRack:0x007fc0c43305b8>

my_app.rb:

class MyApp < Sinatra::Base
  # [...] routes methods

  # utils methods
  def util_method
    return "hi"
  end
end

my_app_test.rb:

require "my_app.rb"
require "test/unit"
require "rack/test"

class MyAppTest < Test::Unit::TestCase
  include Rack::Test::Methods

  def app
    MyApp.new
  end

  # [...] routes methods tests

  def test_util_method
    assert_equal( "hi", app.util_method )
  end
end
4

2 に答える 2

21

Sinatraは、メソッドを再定義する前にエイリアスnewnew!を作成するため、最も簡単な解決策は、代わりにそれを使用することです。

def app
  MyApp.new!
end

もちろん、私は次のことを思いついた後に気づいただけです.


Sinatraを回避してメソッドを再定義しnew、完全な Rack アプリを返し、実際の基本クラスのインスタンスを取得する方法は、「実際の」newメソッドが行うことを自分で行うことです。

def app
  a = MyApp.allocate
  a.send :initialize
  a
end

これはちょっとしたハックですが、テストには役立つかもしれません。

もう 1 つの手法は、クラスに到達するまでミドルウェア スタックを「ウォーク」することです。以下は、名前を使用してスタック内の次のアプリを参照するために関連するすべてのミドルウェアに依存するため、少し壊れやすい@appですが、これはかなり一般的です。

def app
  a = MyApp.new
  while a.class != MyApp
    a = a.instance_variable_get(:@app)
  end
  a
end

ただし、まだリリースされていない Sinatra 1.4 では機能しません (少なくとも、commit 41840746e866e8e8e9a0eaafc53d8b9fe6615b12である現在のマスターでは機能しません) 。これは、クラスnewを返し、ループが終了しないためです。この場合、変数から直接基底クラスを取得できます。Wrapper@instance

def app
  MyApp.new.instance_variable_get :@instance
end

(この最後の手法は、最終的な 1.4 リリースの前に変更される可能性があることに注意してください)。

于 2012-08-22T22:44:13.030 に答える
3

発生している問題は、MyApp.newがMyAppのインスタンスを返すのではなく、アプリをラップするミドルウェアのインスタンス(通常はRack::HeadまたはSinatra::ShowExceptions)を返すことです。良い説明はスレッドSinatraUsageQuestion /RackAppにあります。

私が考えることができる唯一の解決策は、インスタンスメソッドをインスタンス自体なしで呼び出すことができるクラスメソッドに変更することです。アプリのインスタンスはリクエストごとに新たにインスタンス化される可能性があるため、インスタンスメソッドは、シナリオのクラスメソッドに比べてそれほど利点がない可能性があります。

編集:

今後のSinatra1.4では、初期化が変更されます。Sinatra :: Base.newは、#settingsと#helpersを公開するSinatra::Wrapperインスタンスを返します。これは、Sinatra::Baseインスタンスメソッドへのアクセスの問題を解決するのに役立つ場合があります。詳細については、SinatraChangelogを参照してください。

于 2012-08-22T16:27:44.567 に答える