【问题标题】:Stub or mock instance method rspec存根或模拟实例方法 rspec
【发布时间】:2019-10-21 07:54:48
【问题描述】:

以下函数是一个控制器操作,用于从 AWS S3 存储桶获取要提供的数据。

def show
    s3_response = Zlib::GzipReader.new(ApiBucket.bucket.object(id).get.body).read
  render json: s3_response
end

我正在为此方法编写规范。我需要存根/模拟,以使s3_response 实际上并不向 s3 请求。这是我尝试过的。但这不起作用。请帮忙。

describe '#GET show' do
  let!(:resource) { create(:resource) }

  before do
    json_data = Api::V2::Presenter.consume_as_json(resource)
    allow_any_instance_of(Zlib::GzipReader).to receive(:read).and_return(json_data)
  end

  it 'should return the resource in page format' do
    get :show, format: :json, params: { id: resource.uuid }
    response_body_json = JSON.parse(response.body)
    json_data = Api::V2::Presenter.consume_as_json(
        Api::V2::ResourcePresenter.new(resource).page,
        true
      )
    expect(response_body_json).to eql(JSON.parse(json_data))
  end
end

我收到此错误Zlib::GzipFile::Error: not in gzip format

【问题讨论】:

  • 似乎 ApiBucket.bucket.object(id).get.body 发出 S3 请求。你可能应该存根那个。
  • 我不需要吧?不管它是什么反应,我无论如何都会存根Zlib::GzipReader。那么这有什么关系呢?
  • Ruby 仍然计算 ApiBucket.bucket.object(id).get.body 并将其返回值传递给 Zlib::GzipReader.new。然后它调用该对象的read 方法,该方法返回存根响应。所以存根Zlib::GzipReader#read 不会阻止ApiBucket 从 S3 获取原始数据。
  • 没有这样做,而是编写了一个私有控制器,然后将该函数存根
  • 签出 AWS SDK 文档 aws.amazon.com/blogs/developer/…

标签: ruby-on-rails ruby amazon-s3 rspec rspec-rails


【解决方案1】:

而不是存根 Zlib::GzipReaderS3 Bucket。处理这种情况的一种简单易行的方法是在控制器中创建一个新的私有函数,然后存根控制器函数。

在控制器端:

def show
  render json: s3_response
end

private:

def s3_response
   Zlib::GzipReader.new(ApiBucket.bucket.object(id).get.body).read
end

规范将是:

   describe '#GET show' do
  let!(:resource) { create(:resource) }

  before do
    json_data = Api::V2::Presenter.consume_as_json(resource)
    ResourceController.any_instance.stub(:s3_response).and_return(json_data)
  end

  it 'should return the resource in page format' do
    get :show, format: :json, params: { id: resource.uuid }
    response_body_json = JSON.parse(response.body)
    json_data = Api::V2::Presenter.consume_as_json(
        Api::V2::Presenter.new(resource).page,
        true
      )
    expect(response_body_json).to eql(JSON.parse(json_data))
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2013-08-22
    • 2014-07-06
    • 2012-07-27
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多