我正在为一个Web应用程序编写一些测试,其中一个控制器在resolve
对象上调用Scope
,这会返回一个稍微修改过的范围。在测试中,我想将此方法存根以返回原始范围(作为参数传递给Scope.initialize
)。
Scope
对象
class Scope
def initialize(scope)
@scope = scope
end
def resolve
# Return a modified scope.
end
end
控制器
class FooController < ApplicationController
def show
foos = Scope.new(Foo.some_foos).resolve
respond_with foos
end
end
测试
it "does something" do
allow_any_instance_of(Scope).to receive(:resolve).and_return(???.scope)
get :show
# Do some assertions.
end
我需要将???
放在哪里,以便在resolve
的任何实例上存根Scope
方法,以返回创建它的原始范围?
我使用的是Rspec 3.4.2。
答案 0 :(得分:3)
首先,您需要在Scope上创建属性读取器,以便您可以在不使用@scope
的情况下访问instance_variable_get
:
class Scope
attr_reader :scope
def initialize(scope)
@scope = scope
end
def resolve
# Return a modified scope.
end
end
如果使用块实现,接收器将作为第一个arg传递:
allow_any_instance_of(Scope).to receive(:resolve) do |s|
s.scope
end
但强烈建议不要使用allow_any_instance_of
,这通常表明您的测试人员在控制器的工作方式上做了太多而不是实际testing their behavior in a future proof way。
我会使用单元测试来测试Scope
并请求测试控制器的规格以及功能规格。这就是我测试使用Pundit的应用程序的方法,也是一种强大的策略。