I would like to use botocore.stub.Stubber to stub an S3 client, specifically to test code that calls generate_presigned_url. When I use Stubber.add_response with a method of generate_presigned_url, I get an OperationNotFoundError. I suppose this makes sense given that the signature for add_response expects a dictionary for the response param (generate_presigned_url returns just the url), but is this supported in some way or is there a good workaround?
Minimal code to reproduce:
from botocore.stub import Stubber
import boto3
s3 = boto3.client('s3')
stubber = Stubber(s3)
stubber.add_response('generate_presigned_url', 'https://would-be-url')
boto3==1.9.75
botocore==1.12.75
I'm having the same problem. Did you find a solution?
Sorry, I should have posted when I closed the issue. I quickly figured out (and was a little embarrassed that I missed) that generate_presigned_url is not actually an AWS API request like S3::ListBucket or something. It never hits any AWS service at all.
I'm fairly sure it just uses your local credentials to create a signature for the request as if it were going to make it, then puts it in the query parameters of a url that is effectively the request in url form -- signature and all. When you use the url later, it is just a "different format" of API request (i.e. signature + data in query params instead of headers/body/etc) and appears to AWS the same as a normal request if you made it from the client doing the signing. This could be slightly off the mark details wise, but I think it's correct in spirit.
As such, you can just call generate_presigned_url without stubbing whatsoever, it never hits AWS. At least that's what I did in my tests. This may or may not work if you don't have credentials on the machine running the test suite -- I haven't tested that specifically. Additionally, I haven't written tests against the actual output of the generate_presigned_url function, but if you want to I'm sure you could just patch it with mock.
Thank you very much for the detailed answer!
Most helpful comment
Sorry, I should have posted when I closed the issue. I quickly figured out (and was a little embarrassed that I missed) that
generate_presigned_urlis not actually an AWS API request like S3::ListBucket or something. It never hits any AWS service at all.I'm fairly sure it just uses your local credentials to create a signature for the request as if it were going to make it, then puts it in the query parameters of a url that is effectively the request in url form -- signature and all. When you use the url later, it is just a "different format" of API request (i.e. signature + data in query params instead of headers/body/etc) and appears to AWS the same as a normal request if you made it from the client doing the signing. This could be slightly off the mark details wise, but I think it's correct in spirit.
As such, you can just call
generate_presigned_urlwithout stubbing whatsoever, it never hits AWS. At least that's what I did in my tests. This may or may not work if you don't have credentials on the machine running the test suite -- I haven't tested that specifically. Additionally, I haven't written tests against the actual output of thegenerate_presigned_urlfunction, but if you want to I'm sure you could just patch it with mock.