2

I'm trying to use webmock with rspec to stub out requests to Aws but I can't seem to get the regex to work for SQS polling. If I run rspec, webmock generates a 'correct' stub for me to use in a before(:each) block, in my spec_helper.rb like this:

    You can stub this request with the following snippet:

stub_request(:post, "https://sqs.us-west-2.amazonaws.com/123456789012/backlog").
  with(:body => "Action=ReceiveMessage&AttributeName.1=All&MaxNumberOfMessages=1&MessageAttributeName.1=All&QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789012%2Fbacklog&Version=2012-11-05&VisibilityTimeout=0&WaitTimeSeconds=20",
       :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'', 'Authorization'=>'AWS4-HMAC-SHA256 Credential=MY_ACCESS_KEY/20150726/us-west-2/sqs/aws4_request, SignedHeaders=content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=large_alpha-numeric-signature', 'Content-Length'=>'224', 'Content-Type'=>'application/x-www-form-urlencoded; charset=utf-8', 'Host'=>'sqs.us-west-2.amazonaws.com', 'User-Agent'=>'aws-sdk-ruby2/2.1.7 ruby/2.2.2 x86_64-darwin14', 'X-Amz-Content-Sha256'=>'69336339ae76cf370477d4dsaf667as0b5dd8d25762c7c78sad8a', 'X-Amz-Date'=>'20150726T143009Z'}).
  to_return(:status => 200, :body => "", :headers => {})

So in my spec_helper.rb I have

RSpec.configure do |config|
  config.before(:each) do
    stub_request(:post, "https://sqs.us-west-2.amazonaws.com/123456789012/backlog").
      with(:body => "Action=ReceiveMessage&AttributeName.1=All&MaxNumberOfMessages=1&MessageAttributeName.1=All&QueueUrl=https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789012%2Fbacklog&Version=2012-11-05&VisibilityTimeout=0&WaitTimeSeconds=20",
        :headers => {'Accept'=>'*/*',
          'Accept-Encoding'=>'',
          'Authorization'=>"AWS4-HMAC-SHA256 Credential=MY_ACCESS_KEY/20150726/us-west-2/sqs/aws4_request,  SignedHeaders=content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=" + /"^[a-zA-Z0-9]*$"/,
          'Content-Length'=>'224', 
          'Content-Type'=>'application/x-www-form-urlencoded; charset=utf-8',
          'Host'=>'sqs.us-west-2.amazonaws.com',
          'User-Agent'=>'aws-sdk-ruby2/2.1.7 ruby/2.2.2 x86_64-darwin14',
          'X-Amz-Content-Sha256'=>'694236339ae76cf370477d4dsaf667as0b5dd8d25762c7c78sad8a',
          'X-Amz-Date'=>""+ /"^[a-zA-Z0-9]*$"/}).
              to_return(:status => 200, :body => "", :headers => {})
end

The areas I'm trying to use regex against are the Signature and the X-Amz-Date because they're the only two that seem to change between different attempts to run the rspec. The problem is the regex seems to not be working because even though I've added it into the spec_helper.rb, every time I run the suite, I get back the recommended stub from webmock instead of a passing or failing test. It should be passing at this point, from what I understand from the webmock docs and several tutorials. How should I change this to get webmock to work for my test suite against Aws SQS polling? I've been bashing my head against my desk for a few days now so any help is much appreciated.

Adam
  • 344
  • 1
  • 15
  • It doesn't help me understand how to ask better questions by just down voting. If you're going to do it, please tell me why so I can fix it in the future. – Adam May 01 '16 at 22:07

2 Answers2

0

Signature is likely generated using a byproduct of Time.now and I'm guessing you don't actually want to test for that. Instead simply do:

stub_request(:post, "https://sqs.us-west-2.amazonaws.com/123456789012/backlog").and_return(:status => 200, :body => "", :headers => {})

If you want to be even less specific on the URL (like ommiting that ID) you can even use a regex match:

stub_request(:post, /amazonaws.com/).and_return(:status => 200, :body => "", :headers => {})
Anthony
  • 15,435
  • 4
  • 39
  • 69
  • Thanks for the reply, @Anthony. I tried to use that but I just got back the same response from webmock that gives me a suggested stub. Any ideas what I might be missing? – Adam Jul 26 '15 at 15:35
  • even for the second option I posted? – Anthony Jul 26 '15 at 16:16
  • Sorry it's taken so long to get back to you, @Anthony, but yeah, even with the second one i get the same response. – Adam Jul 30 '15 at 21:17
0

I have the same problem and have the solution only for 'X-Amz-Date'.

Since it is date in special format, use Timecop.freeze block around your mock and method call.

Timecop.freeze do
  stub_request(:get, "https://s3.eu-central-1.amazonaws.com/test_bucket/test").
      with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'', 'Authorization'=>'AWS4-HMAC-SHA256 Credential=access_key/20190814/eu-central-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=9e6a6a209a0cb05346a058c12ef706ebff185ae3b72f3e542e1becbc97e8ea7a', 'Content-Length'=>'0', 'Content-Type'=>'', 'Host'=>'s3.eu-central-1.amazonaws.com', 'User-Agent'=>'aws-sdk-ruby2/2.9.44 ruby/2.6.3 x86_64-darwin18 resources', 'X-Amz-Content-Sha256'=>'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'X-Amz-Date'=>"#{time.utc.iso8601(0).gsub(/[^\p{Alnum}]/, '')}"}).
      to_return(status: 200, body: "", headers: {})
  AwsService.bucket.object("test").get
end

The regexp leaves only alphanumerical characters and Timecop takes care of the time.

Dende
  • 545
  • 6
  • 19