dwyl / aws-sdk-mock

:rainbow: AWSomocks for Javascript/Node.js aws-sdk tested, documented & maintained. Contributions welcome!
Apache License 2.0
1.11k stars 110 forks source link

Error passing a sinon stub in mock of `S3.waitFor()` #273

Open azatoth opened 2 years ago

azatoth commented 2 years ago

Since the change introduced by #253 I'm getting an error trying to mock S3.waitFor()

Following test:

/* eslint-disable no-plusplus */
import 'reflect-metadata';

import AWS from 'aws-sdk';
import AWSMock from 'aws-sdk-mock';
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { Readable } from 'stream';

import { getObjectReadStream, waitForObjectExists } from '../src/s3';

chai.use(chaiAsPromised);
chai.use(sinonChai);

describe('S3', () => {
  before(() => {
    AWSMock.setSDKInstance(AWS);
  });
  afterEach(() => {
    AWSMock.restore();
    sinon.restore();
  });
  context('getObjectReadStream', () => {
    it('should return a read stream', () => {
      const getObjectSpy = sinon.spy();
      AWSMock.mock('S3', 'getObject', getObjectSpy);

      const theStream = getObjectReadStream(new AWS.S3(), 'bucket', 'key');

      expect(theStream).to.be.instanceOf(Readable);
      expect(getObjectSpy).to.have.been.calledOnceWith({ Bucket: 'bucket', Key: 'key' });
    });
  });

  context('waitForObjectExists', () => {
    it('should wait for object exists', async () => {
      const getObjectStub = sinon.stub().resolves();
      AWSMock.mock('S3', 'waitFor', getObjectStub);
      await waitForObjectExists(new AWS.S3(), 'bucket', 'key');

      expect(getObjectStub).to.have.been.calledOnceWith('objectExists', {
        Bucket: 'bucket',
        Key: 'key',
      });
    });
  });
});

using following helper functions:

import { S3 } from 'aws-sdk';
import { HeadObjectOutput } from 'aws-sdk/clients/s3';
import { Readable } from 'stream';

export function getObjectReadStream(s3Client: S3, Bucket: string, Key: string): Readable {
  return s3Client.getObject({ Bucket, Key }).createReadStream();
}

export async function waitForObjectExists(
  s3Client: S3,
  Bucket: string,
  Key: string
): Promise<HeadObjectOutput> {
  return s3Client.waitFor('objectExists', { Bucket, Key }).promise();
}

results in following output:

  S3
    getObjectReadStream
      ✔ should return a read stream
    waitForObjectExists
      1) should wait for object exists

  1 passing (14ms)
  1 failing

  1) S3
       waitForObjectExists
         should wait for object exists:
     Error: Expected to spy methods on object but found none
      at walkObject (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core/walk-object.js:39:15)
      at Function.spy (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/spy.js:170:16)
      at Sandbox.spy (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/sandbox.js:383:35)
      at Function.<anonymous> (node_modules/aws-sdk-mock/index.js:131:25)
      at features.constructor.<anonymous> (node_modules/aws-sdk-mock/index.js:250:30)
      at Object.invoke (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/behavior.js:177:32)
      at features.constructor.functionStub (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/stub.js:42:43)
      at Function.invoke (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/proxy-invoke.js:50:47)
      at features.constructor.waitFor (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/proxy.js:280:26)
      at waitForObjectExists (package_dir/src/s3.ts:2:610)
      at Context.<anonymous> (package_dir/tests/s3.test.ts:41:32)
      at processImmediate (internal/timers.js:464:21)

After investigation I notice this issue started in v5.5.0, it works fine in v5.4.0.

azatoth commented 2 years ago

@thomaux, Do you have any idea what could be the issue?

thomaux commented 2 years ago

@azatoth thanks for reporting and detailed reproduce steps. I'll try to make some time next week to look at this. I'll keep ypu posted.

azatoth commented 2 years ago

@thomaux were you able to look into the issue?

ghost commented 1 year ago

Experienced similar issue with passing a fake to getSignedUrl method, with the latest 5.8.0 release of aws-sdk-mock. Downgraded gradually to version 5.4.0 --> here the test started working again.

keithcrooksbbc commented 1 year ago

I am also having the same issue with 5.5.0 - 5.8.0.

As ghost suggests above, downgrading to 5.4.0 resolves the issue.