amazon-archives/aws-sdk-core-ruby

Can't stub responses for dynamodb get_item

Closed this issue · 3 comments

Hi,

I'm having an issue with stubbing responses for the dynamodb get_item request, because my stubbed item fails parameter validation.

In my spec I have:

client = Aws::DynamoDB::Client.new(stub_responses: true)
client.stub_responses(:get_item, {item: {'some-field' => 'some-value'}})

But this produces the following error:

 Failure/Error: client.stub_responses(:get_item, {item: {'some-field' => 'some-value'}})
     ArgumentError:
       expected params[:item]["some-field"] to be a hash

I noticed that in the response structure documentation it shows "AttributeName" => Hash, although the text beneath says:

An attribute value may be one of:

* Hash
* Array
* String
* Numeric
* true | false
* nil
* IO
* Set<String,Numeric,IO>

I've verified with live requests and am getting item back as a hash of string => string in the response, so I think it should be valid to define a stub as I have done?

I see what is going on here. The actual DynamoDB API accepts and returns item attribute values in a very different format than the SDK accepts and returns. The actual DynamoDB format requires that the type is serialized with the value. The SDK ships with a customization that accepts native Ruby types and then converts them to the format expected by DynamoDB.

To pass the response stubbing validation, you would need to provide the "serialized" format of the params, for example:

Aws> client = Aws::DynamoDB::Client.new(stub_responses: true)
Aws> client.stub_responses(:get_item, {item: {'some-field' => { s: 'some-value' }}})

By replacing the string value with {s:'some-vaue'}, the response stubbing will accept the value. Unfortunately, the natural followup request will not work as intended:

Aws> client.get_item(table_name:'aws-sdk', key:{'id' => '1'})
[Aws::DynamoDB::Client 0 0.002319 0 retries] get_item(table_name:"aws-sdk",key:{"id"=>{s:"1"}})  
=> #<struct 
 item=
  {"some-field"=>
    #<struct 
     s="some-value",
     n="NumberAttributeValue",
     b=nil,
     ss=[],
     ns=[],
     bs=[],
     m={},
     l=[],
     null=false,
     bool=false>},
 consumed_capacity=nil>

Notice the response value from the stubbed client has not been translated to the native ruby type of String. I'm going to mark this as a bug as this is not the expected behavior. The goal is to support what you attempted to do in the first place.

Thank you for reporting this issue. As a work-around, you might consider using DynamoDB Local. This should eliminate the need to stub responses and may be a better testing experience in the long run.

@acoulton I'm closing this issue as I've opened a new issue against the main repository over here:
aws/aws-sdk-ruby#770

@trevorrowe thanks very much. DynamoDB Local looks a bit heavyweight for my current very simple usecase, so I'm just working around with traditional rspec-mocks for now which is doing what I need. But it's useful to know it exists!