m-radzikowski / aws-sdk-client-mock

AWS JavaScript SDK v3 mocks for easy unit testing. 🖋️ Typed 🔬 Tested 📄 Documented 🛠️ Maintained
https://m-radzikowski.github.io/aws-sdk-client-mock/
MIT License
765 stars 38 forks source link

S3 Presign #62

Open kochie opened 2 years ago

kochie commented 2 years ago

S3 presign is done using a helper library @aws-sdk/s3-request-presigner this seems like something that would need a helper library or additional documentation to mock properly.

It would be good to see a way to mock presign requests. I'm happy to help with this.

m-radzikowski commented 2 years ago

I looked at it and I think mocking it is not (easily) possible right now with the lib.

Presign is done by a middleware. getSignedUrl() is creating the middleware and makes the send() call. Middleware intercepts the command, generates signed URL, and returns the result instead of proceeding with actually sending the command to AWS. See: https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/src/getSignedUrl.ts

The mocking lib does not mock middlewares, but only client send() command. Mocking middleware can be especially hard in this case, since it's created locally in the getSignedUrl() function.

I think the way to go is to mock the whole getSignedUrl() function.

Feel free to submit a PR for this!

kochie commented 2 years ago

Yeah so at the moment my strategy has been to mock getSignedUrl() and this works but it's a pretty basic mock. I'll look into it but might take some time. I'll post here if I have any updates.

arunachalamN commented 2 years ago

Yeah, this functionality would be great.

ShogunPanda commented 2 years ago

An alternative solution is to mock your URL command to return a {presigned: require('url').parse('http://url')}. At least, it worked for me on PutObject.

jhecking commented 1 year ago

The best solution I've found is from the referenced issue:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl') // eslint-disable-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment

sinon.stub(presigner, 'getSignedUrl').resolves('https://s3.amazonaws.com/path/to/object')
pagameba commented 9 months ago

I get an error with this (sinon.stub)

TypeError: Descriptor for property getSignedUrl is non-configurable and non-writable
Roger13 commented 6 months ago

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

major-mayer commented 4 months ago

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

This works great, but you need to expose (fake) AWS credentials, or otherwise it will complain.

CredentialsProviderError: Could not load credentials from any providers
major-mayer commented 4 months ago

Similar behaviour can be achieved for createPresignedPost from s3-presigned-post.

const postPresigner = require('@aws-sdk/s3-presigned-post/dist-cjs/createPresignedPost.js')
jest.spyOn(postPresigner, 'createPresignedPost').mockResolvedValue({ url: 'mockValue',
    fields: {
        key: 'mockValue',
        Policy: 'mockValue',
        'X-Amz-Signature': 'mockValue',
        'X-Amz-Security-Token': 'mockValue',
        bucket: 'mockValue',
        'X-Amz-Algorithm': 'mockValue',
        'X-Amz-Credential': 'mockValue',
        'X-Amz-Date': 'mockValue',
    } })
Ribosom commented 3 months ago

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

Thank you. I had to change it, but your approach helped me.

My solution:

jest.mock("@aws-sdk/s3-request-presigner", () => {
  return {
    getSignedUrl: jest.fn().mockResolvedValueOnce(signedUrlMockValue),
  };
});
garysassano commented 3 months ago

This is how I've done using jest:

const presigner = require('@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl')
jest.spyOn(presigner, 'getSignedUrl').mockResolvedValueOnce(signedUrlMockValue)

Thanks for the simple solution @jhecking 🙌

This solution doesn't work anymore starting from SDK v3.495.0 unfortunately.

Krrish92 commented 2 months ago

Is there any PR open to support getSignedUrl mock ? I am completely blocked as work around discussed above as well not working with new version of sdk

m-radzikowski commented 1 month ago

If someone wants to create a PR, I will gladly review it.

voslartomas commented 1 week ago

For those still struggling with this issue even today, you can workaround it with reimporting getSignedUrl to your own module like described in here https://stackoverflow.com/questions/72616800/trying-to-stub-a-function-results-in-descriptor-for-property-is-non-configurable/72793194#72793194