Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocking @aws-sdk/s3-request-presigner getSignedUrl causes sinon.stub to throw non-configurable or non-writable properties #3689

Closed
JaredAAT opened this issue Jun 15, 2022 · 3 comments
Assignees
Labels
feature-request New feature or enhancement. May require GitHub community feedback. workaround-available This issue has a work around available.

Comments

@JaredAAT
Copy link

JaredAAT commented Jun 15, 2022

Describe the bug

There doesn't seem to be a nice way to test getSignedUrl from @aws-sdk/s3-request-presigner. Using sinon to try and stub out the function results in TypeError: Descriptor for property getSignedUrl is non-configurable and non-writable from this code:

const s3RequestSigner = require("@aws-sdk/s3-request-presigner");
const expect = require('chai').expect;
const sinon = require('sinon')
....
it('should throw an error when getSignedUrl rejects', async function() {
  const sandbox = sinon.createSandbox();
  sandbox.stub(s3RequestSigner, "getSignedUrl").rejects("fakeUrl");
  sandbox.restore();
})

This is because sinon throws when obj.prop is a synthetic getter: sinonjs/sinon#2377

Expected Behavior

I would expect that I can mock getSignedUrl to resolve or reject however I want using something like sinon to stub/spy/mock out the functionality.

Current Behavior

Sinon throws TypeError: Descriptor for property getSignedUrl is non-configurable and non-writable

Reproduction Steps

Create a test environment using jasmine or mocha, install sinon, chai, @aws-sdk/s3-request-presigner and @aws-sdk/client-s3. Try and mock out getSignedUrl with code such as:

const s3RequestSigner = require("@aws-sdk/s3-request-presigner");
const expect = require('chai').expect;
const sinon = require('sinon')

describe('trying to mock getSignedUrl', () => {
  it('should throw an error when getSignedUrl rejects', async function() {
    const sandbox = sinon.createSandbox();
    sandbox.stub(s3RequestSigner, "getSignedUrl").rejects("fakeUrl");
    sandbox.restore();
  })
})

Possible Solution

Not a solution for Amazon, but for anyone else struggling with this issue, you can use proxyquire to replace s3-request-presigner like thus:

const sinon = require('sinon')
const proxyquire =  require('proxyquire')
...
it('should throw an error when getSignedUrl rejects', async function() {
    const fakeurl = 'hello world'
    const fakeURL = sinon.stub().resolves(fakeurl)
    const handler = proxyquire(
      '../../handlers/presigned_url',
      {
        '@aws-sdk/s3-request-presigner': {
          'getSignedUrl': async () => {
            return fakeURL()
          }
        }
      }
    )
})

But you might run into other issues depending on how your tests and code is written.

Additional Information/Context

No response

SDK version used

3.109.0

Environment details (OS name and version, etc.)

node.js 16, sinon 14.0.0, chai 4.3.6, jasmine 4.2.0, OS X 12.2.1

@JaredAAT JaredAAT added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jun 15, 2022
@ajredniwja ajredniwja self-assigned this Jun 16, 2022
@ajredniwja ajredniwja added the workaround-available This issue has a work around available. label Jun 16, 2022
@ajredniwja
Copy link
Contributor

Hey @JaredAAT thanks for opening this issue and apologies it fell out of the queue. You can use https://github.com/m-radzikowski/aws-sdk-client-mock which uses sinon under the hood too and is recommended by the team. However the error coming from sinon, I wont consider it to be a bug with the SDK. The library mentioned has some problems with mock presign requests see m-radzikowski/aws-sdk-client-mock#62 (comment)

@ajredniwja ajredniwja added feature-request New feature or enhancement. May require GitHub community feedback. and removed bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 3, 2022
@lqvinh243
Copy link

lqvinh243 commented Mar 18, 2023

I had same problem when I trying to stub getSignedUrl, but I found a solution just using sinon

import * as s3RequestPresigner from '@aws-sdk/s3-request-presigner/dist-cjs/getSignedUrl';

describe('Generate get signed url', () => {
    it('Error', async () => {
      const errorStub = sandbox.stub(s3RequestPresigner, 'getSignedUrl').rejects(errorObject);

      const error: Error = await storage.yourFunctionStub(bucketName, urlPath).catch((error) => error);
      sandbox.assert.calledOnce(errorStub);
      expect(error.message).to.eq(errorObject.message);
    });

    it('Success, async () => {
      const url = `${baseUrl}/${bucketName}-${Date.now()}`;
      const successStub = sandbox.stub(s3RequestPresigner, 'getSignedUrl').resolves(url);

      const result = await storage.yourFunctionStub(bucketName, urlPath);
      sandbox.assert.calledOnce(successStub);
      expect(result).to.eq(url);
    });
  });

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request New feature or enhancement. May require GitHub community feedback. workaround-available This issue has a work around available.
Projects
None yet
Development

No branches or pull requests

4 participants