2

だから私はこの単純なルビークラスを持っています:

class GetRequestList
  def initialize(current_user, filter_hash)
    @authorizer = RequestAuthorizer.new(current_user)
    @filter    = RequestFilter.new(filter_hash)
  end
  def generate
    Request.send_chain(@authorizer.method_chain)
           .send_chain(@filter.method_chain)
  end
end

そして、実装の分離でRequest2つのメソッドを受け取ることをテストしたいと思います。そのために、いくつかのスタブを使用しようとしています:send_chainRequestAuthorizerRequestFilter

require 'test_helper'

class GetRequestListTest < ActiveSupport::TestCase

  test "request should be filtered by filter and role" do
    Request.expects(:send_chain).twice.returns([build(:request)])
    RequestFilter.stubs(:new)
    RequestFilter.any_instance.stubs(:method_chain).returns([])
    RequestAuthorizer.stubs(:new)
    RequestAuthorizer.any_instance.stubs(:method_chain).returns([])
    assert GetRequestList.new(:current_user, :filter).generate.size == 1
  end
end

何が間違っているかがわかります。stubs(:new)が返され、インスタンス変数のnilインスタンスがなく、エラーが発生します。インスタンス変数でメソッドをスタブ化する方法がわかりません。助言がありますか?RequestAuthorizerRequestFilterGetRequestList

4

3 に答える 3

5

スタブアウトnewして値を返さない代わりに、何かを返すようにします。

mock_request_filter = mock()
RequestFilter.stubs(:new).returns(mock_filter)

これにより、スタブを読み取ることもできます-代わりにany_instanceそれらを設定するだけです。mock_request_filter

于 2013-06-30T19:04:15.843 に答える
1

これが、インスタンス変数をメソッド内にラップする必要がある理由です。このアプローチを見てください。このようにして、テストは RequestFilter または RequestAuthorizer について認識しません。そして今、あなたはそれらをパラメーターとして取得することも資産にしています。オーソライザーとフィルターの初期化もメソッド内にラップしていることに注意してください。メインの初期化メソッドがさらに多くのものを取得する場合は、両方を別のものにラップすることもできます。

class GetRequestList
  def initialize(current_user, filter_hash)
    initialize_authorizer
    initialize_filter
  end

  def generate
    Request.send_chain(authorizer_method_chain)
           .send_chain(filter_method_chain)
  end

  private

  def initialize_authorizer
    @authorizer = RequestAuthorizer.new(current_user)
  end

  def initialize_filter
    @filter = RequestFilter.new(filter_hash)
  end

  def authorizer_method_chain
    @authorizer.method_chain
  end

  def filter_method_chain
    @filter.method_chain
  end
end

そしてテスト

require 'test_helper'

class GetRequestListTest < ActiveSupport::TestCase

  test "request should be filtered by filter and role" do
    get_request_list = GetRequestList.new(:current_user, :filter)
    get_request_list.stubs(:initialize_authorizer)
    get_request_list.stubs(:initialize_filter)

    get_request_list.stubs(:authorizer_method_chain).returns(:authorizer_method_chain)
    get_request_list.stubs(:filter_method_chain).returns(:filter_method_chain)

    Request.expects(:send_chain).with(:authorizer_method_chain).returns([build(:request)])
    Request.expects(:send_chain).with(:filter_method_chain).returns([build(:request)])

    assert get_request_list.generate.size == 1
  end
end

また、シンボルを使用してオーソライザー オブジェクトとフィルター オブジェクトを置き換えました。それらをモックにする必要さえないからです。1や などの他のもの2でもかまいませんが、シンボルや文字列を保持すると、物事に適切な名前を付けることができます。

于 2013-06-30T19:13:41.093 に答える