Skip to content

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

@azatoth

Description

@azatoth

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions