如何在存根时访问对象的实例变量?

时间:2016-12-11 23:42:47

标签: ruby-on-rails ruby rspec instance-variables

我正在为一个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。

1 个答案:

答案 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的应用程序的方法,也是一种强大的策略。