How to Mock Aws Sdk (V2) with Rspec

How do I mock AWS SDK (v2) with rspec?

I had a hard time finding examples mocking AWS resources. I spent a few days figuring it out and wanted to share my results on Stack Overflow for posterity. I used rspec-mocks (doubles & verifying doubles). Here's an example with the communicator.rb example in the question.

communicator_spec.rb:

RSpec.describe Communicator do
describe "#consume_messages" do
it "can use rspec doubles & verifying doubles to mock AWS SDK calls" do
sqs_client = instance_double(Aws::SQS::Client)
allow(Aws::SQS::Client).to receive(:new).and_return(sqs_client)
SQSResponse = Struct.new(:messages)
SQSMessage = Struct.new(:body, :receipt_handle)
response = SQSResponse.new([SQSMessage.new(File.read('data/expected_body.json'), "receipt_handle")])
empty_response = SQSResponse.new([])
allow(sqs_client).to receive(:receive_message).
and_return(response, empty_response)
allow(sqs_client).to receive(:delete_message).and_return(nil)

Communicator.new.consume_messages
end
end
end

How to mock aws-sdk gem?

There are a lot of ways to mock requests in the AWS SDK for Ruby. Trevor Rowe recently posted an article on using the SDK's native support for object stubbing, which does not require any external dependencies like Webmock. You can also use tools like VCR (link will send you to another blog post) to build cacheable integration tests; this way you can test against the live service when you want accuracy and avoid hitting network when you want speed.

Regarding the get request on latest/meta-data/iam/security-credentials/, this happens because the SDK is trying to look up credentials, and, if none are provided, it will check if you are running on an EC2 instance as a last resort, causing the SDK to make an extra HTTP request. You can avoid this check by simply providing bogus static credentials, though if you are using something like VCR, you will want to provide valid credentials for the first run. You can read about how to provide static credentials in another blog post that Trevor wrote on credential management (this should also be in the developer guide and SDK documentation).

How to mock aws-sdk gem?

There are a lot of ways to mock requests in the AWS SDK for Ruby. Trevor Rowe recently posted an article on using the SDK's native support for object stubbing, which does not require any external dependencies like Webmock. You can also use tools like VCR (link will send you to another blog post) to build cacheable integration tests; this way you can test against the live service when you want accuracy and avoid hitting network when you want speed.

Regarding the get request on latest/meta-data/iam/security-credentials/, this happens because the SDK is trying to look up credentials, and, if none are provided, it will check if you are running on an EC2 instance as a last resort, causing the SDK to make an extra HTTP request. You can avoid this check by simply providing bogus static credentials, though if you are using something like VCR, you will want to provide valid credentials for the first run. You can read about how to provide static credentials in another blog post that Trevor wrote on credential management (this should also be in the developer guide and SDK documentation).

Stub or mock instance method rspec

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

Stub Calls to `Aws.config.update()`

Stubbing without specifying a return value has the effect you intend, for example:

expect(Aws.config).to receive(:update)

afer this, running Aws.config.update will just return nil and not actually run anything. You could also use allow.

You didn't specify what testing library you're using, but to be clear the example I gave is in RSpec.



Related Topics



Leave a reply



Submit