2

所以我有这个简单的 ruby​​ 类:

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

而且我想测试Request接收两种send_chain方法的隔离RequestAuthorizerRequestFilter实现。为此,我正在尝试使用一些存根:

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并且没有实例RequestAuthorizerRequestFilter实例变量,GetRequestList我们得到一个错误。我不知道如何在实例变量上存根方法。有什么建议么?

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

我还使用了一个符号来替换授权者和过滤器对象,因为您甚至不需要它们来模拟。它也可以是其他的东西,比如1and 2,但是保留符号或字符串可以让你正确地命名事物。

于 2013-06-30T19:13:41.093 回答
0

您是否尝试过公开实例变量以便对它进行存根?

GetRequestList.new(:current_user, :filter).tap do |it|
  def it.authorizer
    @authorizer
  end
  install_stubs(it.authorizer)
end.generate
于 2015-04-10T19:01:20.537 回答