AWS Developer Tools Blog
Stubbing AWS Responses
I come across questions frequently about how to test an application that uses the AWS SDK for Ruby (aws-sdk
gem). Testing an application that makes use of an external service is always tricky. One technique is to stub the client-level responses returned by the SDK.
AWS.stub!
Calling the AWS.stub!
method in your ruby process configures the client classes (e.g. AWS::EC2::Client
) to stub their responses when called. They stop short of making a live HTTP request and instead return an empty response.
AWS.stub! instance_ids = AWS::EC2.new.instances.map(&:id) instance_ids #=> will always be empty in this example, not HTTP request made
Under the covers, the code example is constructing an AWS::EC2::Client
object and is calling the #describe_instances
method. AWS.stub!
causes the client to return an empty response that looks like a normal response with a few differences:
- Lists are returned as empty arrays
- Maps are returned as empty hashes
- Numeric values are always zero
- Dates are returned as now
Localized Stubbing
Calling AWS.stub!
is the same as calling AWS.config(:stub_requests => true)
. You can use this configuration option with any constructor that accepts configuration.
stub_ec2 = AWS::EC2.new(:stub_requests => true) real_ec2 = AWS::EC2.new
Customizing the Responses
In addition to getting empty responses, you can access the stubbed responses and populate them with fake data.
AWS.stub! ec2 = AWS::EC2::Client.new resp = ec2.stub_for(:describe_instances) resp.data[:reservation_set] = [...] # now calling ec2.describe_instances will return my fake data ec2.describe_instances #=> { :reservation_set => [...] }
There are two methods you can use here:
#stub_for(operation_name)
#new_stub_for(operation_name)
The first method, #stub_for
, returns the same stubbed response every time. It is the default response for that operation for that client object (not shared between instances). The second method, #new_stub_for
, generates a new response. This is useful if you need to stub the client to return different data from multiple calls. This is common for paged responses.
Not a Mock
Unfortunately, this approach stubs responses, but it does not mock AWS services. If I used a stubbed AWS::DynamoDB::Client
and call #put_item
, I will not be able to get the data back. There are a number of third-party libraries that attempt to provide local service mocks. These can be helpful when you are trying to run local tests without hitting the network.