Last active
June 21, 2024 06:41
-
-
Save rokumatsumoto/e5f2e9ac027e2c8e2f88a3e6a5a5065d to your computer and use it in GitHub Desktop.
Stubbing the AWS SDK S3 (bucket.object, bucket.object.exists? methods and bucket.object.exists? responses)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Gemfile | |
gem 'aws-sdk-s3' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/aws.rb | |
credentials = Aws::Credentials.new( | |
Boyutluseyler.config[:direct_upload_access_key_id], | |
Boyutluseyler.config[:direct_upload_secret_access_key] | |
) | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Resource.html | |
DIRECT_UPLOAD_RESOURCE = Aws::S3::Resource.new( | |
stub_responses: Rails.env.test?, | |
region: Boyutluseyler.config[:direct_upload_region], | |
credentials: credentials | |
) | |
DIRECT_UPLOAD_BUCKET = DIRECT_UPLOAD_RESOURCE.bucket(Boyutluseyler.config[:direct_upload_bucket_name]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/support/helpers/stub_aws_responses.rb | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Resource.html | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html | |
# Stubbing the AWS SDK | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/stubbing.html | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ClientStubs.html | |
# https://aws.amazon.com/blogs/developer/advanced-client-stubbing-in-the-aws-sdk-for-ruby-version-3/ | |
# https://stelligent.com/2016/04/14/using-stubs-for-the-aws-sdk-for-ruby-2/ | |
# https://semaphoreci.com/community/tutorials/stubbing-the-aws-sdk | |
module StubAWSResponses | |
def stub_direct_upload_bucket_object_is_not_exist | |
DIRECT_UPLOAD_RESOURCE.client.stub_responses(:head_object, | |
status_code: 404, | |
headers: {}, | |
body: '') | |
end | |
def stub_direct_upload_bucket_object_exists | |
DIRECT_UPLOAD_RESOURCE.client.stub_responses(:head_object, | |
status_code: 200, | |
headers: {}, | |
body: '') | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/spec_helper.rb | |
RSpec.configure do |config| | |
config.include StubAWSResponses | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/services/blueprints/build_service.rb | |
# frozen_string_literal: true | |
module Blueprints | |
class BuildService < Blueprints::BaseService | |
prepend ValidatesRemoteObject | |
def execute | |
validate! | |
Blueprint.new.tap do |b| | |
b.url = remote_object.public_url | |
b.url_path = remote_object.key | |
b.size = remote_object.size | |
b.content_type = remote_object.content_type | |
b.thumb_url = '' | |
end | |
end | |
private | |
def validate! | |
raise ValidationError, 'File not found' unless remote_object_exists? | |
end | |
def bucket | |
ObjectStorage::DirectUpload::Bucket | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/services/concerns/validates_remote_object.rb | |
# frozen_string_literal: true | |
module ValidatesRemoteObject | |
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#exists%3F-instance_method | |
delegate :exists?, to: :remote_object, prefix: true | |
def remote_object | |
@remote_object ||= bucket.object(key) | |
end | |
def bucket | |
super || (raise NotImplementedError, | |
'"bucket" must be implemented and return an Aws::S3::Bucket') | |
end | |
def key | |
params[:key] || (raise ArgumentError, 'Key needs to be specified') | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/object_storage/direct_upload/bucket.rb | |
# frozen_string_literal: true | |
# Wrapper class for AWS::S3::Bucket | |
require_relative 'presigned_post' | |
module ObjectStorage | |
module DirectUpload | |
class Bucket | |
class << self | |
delegate :object, to: :bucket | |
def bucket | |
@bucket ||= DIRECT_UPLOAD_BUCKET | |
end | |
def presigned_post(policy) | |
PresignedPost.new(bucket, policy).create | |
end | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/services/blueprints/build_service_spec.rb | |
# frozen_string_literal: true | |
require 'spec_helper' | |
RSpec.describe Blueprints::BuildService do | |
describe 'modules' do | |
it { is_expected.to include_module(ValidatesRemoteObject) } | |
end | |
describe '#execute' do | |
subject(:service) { described_class.new(user, params) } | |
let(:user) { build_stubbed(:user) } | |
let(:params) { { key: 'model.stl' } } | |
let(:validation_error) { described_class::ValidationError } | |
context 'when the remote object is not exist' do | |
before do | |
stub_direct_upload_bucket_object_is_not_exist | |
end | |
after do | |
stub_direct_upload_bucket_object_exists # default stub behavior | |
end | |
it 'raises a file not found error' do | |
expect { service.execute }.to raise_error(validation_error, 'File not found') | |
end | |
end | |
context 'when the remote object exists' do | |
it 'builds a blueprint without saving it' do | |
direct_upload_bucket = class_double(ObjectStorage::DirectUpload::Bucket).as_stubbed_const | |
# stubbing Aws::S3::Object | |
remote_object = double(key: 'model.stl', size: 1, content_type: 'model/stl', | |
public_url: 'http://foo.com/model.stl', exists?: true) | |
allow(direct_upload_bucket).to receive(:object).and_return(remote_object) | |
result = service.execute | |
expect(result).to be_valid | |
expect(result).not_to be_persisted | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment