The below function is a controller action and gets the data to be served from an AWS S3 bucket.
def show
s3_response = Zlib::GzipReader.new(ApiBucket.bucket.object(id).get.body).read
render json: s3_response
end
I am writing a spec for this method. I need to stub/mock such that s3_response
doesn't actually request from s3. Here is what I tried. This doesn't work though. Please help.
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
I am getting this error Zlib::GzipFile::Error: not in gzip format
Instead of stubbing Zlib::GzipReader
or the S3 Bucket
. One simple and easy way to handle such cases would be to create a new private function in the controller and then stub the controller function.
In the controller side:
def show
render json: s3_response
end
private:
def s3_response
Zlib::GzipReader.new(ApiBucket.bucket.object(id).get.body).read
end
The spec will be:
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