所以我有这个简单的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
方法,而不是RequestAuthorizer
和RequestFilter
实现。要做到这一点,我试图使用一些存根:
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
,RequestAuthorizer
的实例变量中没有RequestFilter
和GetRequestList
的实例,我们收到错误消息。我无法弄清楚如何在实例变量上存根方法。
有什么建议吗?
答案 0 :(得分:4)
不要将new
删除而不返回任何值,而是让它返回一些内容,例如
mock_request_filter = mock()
RequestFilter.stubs(:new).returns(mock_filter)
这也使您能够阅读any_instance
上的存根 - 只需将其设置为mock_request_filter
。
答案 1 :(得分: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
之类的其他东西,但保留符号或字符串可以让你有点名字。
答案 2 :(得分:0)
您是否尝试过暴露实例变量以便将其存根?
GetRequestList.new(:current_user, :filter).tap do |it|
def it.authorizer
@authorizer
end
install_stubs(it.authorizer)
end.generate