stubbing class inside controllers 动作

stubbing class inside controllers action

是否可以对 class 内部控制器操作进行存根?

我想将 SomeServiceObject 存根到 return 假值,以便我获得 else 语句。

# controllers/users_controller.rb

...

def index
  service = SomeServiceObject.new(...)

  if service.perform
    render json: { code: 100 }
  else
    render json: { code: 200 } 
  end
end

...

我尝试了这个,但没有成功

# users_controller_spec.rb

...

allow(SomeServiceObject).to receive(:perform).and_return(false)

...

我认为最好的方法是通过 instance_double

let(:some_service_object) { instance_double(SomeServiceObject) }

before do
  allow(SomeServiceObject).to receive(:new).and_return(some_service_object)
  allow(some_service_object).to receive(:perform).and_return(false)
end

另一种方法是使用 any_instance_of:

allow_any_instance_of(SomeServiceObject).to receive(:perform).and_return(false)

但是您可能会收到警告,指出 any_instance 已弃用,不建议在测试中使用。你可以在这里阅读更多关于原因的信息:

https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance

这里:

any_instance is the old way to stub or mock any instance of a class but carries > > the baggage of a global monkey patch on all classes. Note that we generally recommend against using this feature

https://relishapp.com/rspec/rspec-mocks/v/3-3/docs/old-syntax/any-instance