Skip to content

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

Closed
@JaredAAT

Description

@JaredAAT

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

Metadata

Metadata

Assignees

Labels

feature-requestNew feature or enhancement. May require GitHub community feedback.workaround-availableThis issue has a work around available.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions