在AWS Ruby SDK v2中Stub S3预签名URL遇到问题
解决AWS SDK v2.3.22中Stub预签名URL的问题
我帮你搞定这个问题——在AWS SDK v2.3.22里,Stub预签名URL确实不能直接针对Resource层的presigned_url方法来搞,得找对底层的调用点才行。
核心原理
S3 Resource对象的presigned_url方法本质是封装了底层Client的generate_presigned_url方法。所以你要Stub的目标不是Resource层的方法,而是Aws::S3::Client#generate_presigned_url这个核心方法。
具体实现代码
结合你的S3Helper模块,下面是完整的测试示例(基于RSpec):
describe 'Stubbing AWS' do module S3Helper def self.presigned_url(object_key:, client:) resource = ::Aws::S3::Resource.new(client: client) bucket = resource.bucket('my-great-bucket') # 假设你需要生成PUT操作的预签名URL bucket.object(object_key).presigned_url(:put) end end it 'returns a stubbed presigned URL for valid requests' do # 1. 创建带Stub功能的S3 Client实例 stub_client = Aws::S3::Client.new(stub_responses: true) # 2. 预设generate_presigned_url的返回结果 expected_presigned_url = 'https://my-great-bucket.s3.amazonaws.com/test-key?X-Amz-Algorithm=AWS4-HMAC-SHA256&...' stub_client.stub_responses( :generate_presigned_url, expected_presigned_url ) # 3. 调用Helper方法并断言结果 result = S3Helper.presigned_url(object_key: 'test-key', client: stub_client) expect(result).to eq(expected_presigned_url) end it 'handles errors when generating presigned URLs' do stub_client = Aws::S3::Client.new(stub_responses: true) # 模拟签名错误的场景 stub_client.stub_responses( :generate_presigned_url, Aws::S3::Errors::SignatureDoesNotMatch.new(nil, 'Invalid signature provided') ) # 断言会抛出对应的错误 expect { S3Helper.presigned_url(object_key: 'test-key', client: stub_client) }.to raise_error(Aws::S3::Errors::SignatureDoesNotMatch) end it 'matches specific request parameters for precision' do stub_client = Aws::S3::Client.new(stub_responses: true) # 只针对特定bucket、key和操作返回预设URL,其他情况返回错误 stub_client.stub_responses( :generate_presigned_url, lambda do |context| if context.params[:bucket] == 'my-great-bucket' && context.params[:key] == 'target-key' && context.params[:method] == :put 'https://my-great-bucket.s3.amazonaws.com/target-key?valid-signature' else Aws::S3::Errors::NoSuchBucket.new(nil, 'Bucket not found') end end ) # 测试匹配的情况 valid_result = S3Helper.presigned_url(object_key: 'target-key', client: stub_client) expect(valid_result).to include('target-key?valid-signature') # 测试不匹配的情况 expect { S3Helper.presigned_url(object_key: 'wrong-key', client: stub_client) }.to raise_error(Aws::S3::Errors::NoSuchBucket) end end
关键注意点
- 确保你Stub的是
generate_presigned_url方法,这是SDK内部生成预签名URL的核心入口 - 如果你需要区分不同的操作(PUT/GET)或资源(bucket/key),可以用lambda来做条件匹配
- 错误Stub需要使用SDK内置的错误类(比如
Aws::S3::Errors::SignatureDoesNotMatch),才能和实际场景的错误类型对齐
内容的提问来源于stack exchange,提问作者Nick Tomlin
相关产品推荐
相关产品推荐

