nodejs: How to stub AWS s3 getobject with sinon
Asked Answered
F

1

7

I am trying to write unit tests but am having trouble stubbing the AWS S3 getobject method. Here is my code:

describe('testExecuteSuccess()', function () {
    it('Test execution with id is successful.', async () => {
        let id = "test_id";
        const getObjectStub = AWS.S3.prototype.getObject = sinon.stub();
        getObjectStub.returns({ promise: () => Promise.resolve({ Body: "test" }) });
        await executionHandler.execute(id).then(() => {
            getObjectStub.should.have.been.calledOnce;
        });
    });
});

Does anyone know what is wrong with it/how to properly stub the getObject method? When I run the test, I am getting InvalidParameterType: Expected params.Bucket to be a string which proves that the stub is not working.

Here is the code to the executionHandler.execute method:

exports.execute = async function(curr_id) {
    let params = { Bucket: BUCKET_NAME, Key: KEY_PATH }
    let fileObject = await s3.getObject(params).promise();
    let codeId = executeCode(fileObject).id;
    if (codeId !== curr_id) {
        throw "Id from executed code does not match currentId: " + curr_id;
    }
}

Note: I am using Mocha test runner.

Fredia answered 22/8, 2018 at 4:22 Comment(2)
could you add the code you are executing (executionHandler.execute) to the description and also which test runner you are using, thanks.Pentachlorophenol
@PeterGrainger Sure, I have edited the description. Thanks.Fredia
T
4

You can stub out dependencies such as aws-sdk module with link seams. This is the CommonJS version, so we will be using proxyquire to construct our seams.

unit test solution:

main.js:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.execute = async function (curr_id) {
  const BUCKET_NAME = 'examplebucket';
  const KEY_PATH = 'SampleFile.txt';
  let params = { Bucket: BUCKET_NAME, Key: KEY_PATH };
  let fileObject = await s3.getObject(params).promise();
  let codeId = executeCode(fileObject).id;
  if (codeId !== curr_id) {
    throw 'Id from executed code does not match currentId: ' + curr_id;
  }
};

function executeCode(file) {
  return file;
}

main.test.js:

const proxyquire = require('proxyquire');
const sinon = require('sinon');
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');

chai.use(chaiAsPromised);
const { expect } = chai;

describe('51959840', () => {
  afterEach(() => {
    sinon.restore();
  });
  it('should do nothing if codeId is equal with curr_id', async () => {
    const fileObject = { id: '1' };
    const s3Mock = {
      getObject: sinon.stub().returnsThis(),
      promise: sinon.stub().resolves(fileObject),
    };
    const AWSMock = { S3: sinon.stub().returns(s3Mock) };
    const { execute } = proxyquire('./main', {
      'aws-sdk': AWSMock,
    });
    await execute('1');
    sinon.assert.calledOnce(AWSMock.S3);
    sinon.assert.calledWithExactly(s3Mock.getObject, { Bucket: 'examplebucket', Key: 'SampleFile.txt' });
    sinon.assert.calledOnce(s3Mock.promise);
  });

  it('should throw error if codeId is NOT equal with curr_id', async () => {
    const fileObject = { id: '2' };
    const s3Mock = {
      getObject: sinon.stub().returnsThis(),
      promise: sinon.stub().resolves(fileObject),
    };
    const AWSMock = { S3: sinon.stub().returns(s3Mock) };
    const { execute } = proxyquire('./main', {
      'aws-sdk': AWSMock,
    });
    await expect(execute('1')).to.rejectedWith('Id from executed code does not match currentId: 1');
    sinon.assert.calledOnce(AWSMock.S3);
    sinon.assert.calledWithExactly(s3Mock.getObject, { Bucket: 'examplebucket', Key: 'SampleFile.txt' });
    sinon.assert.calledOnce(s3Mock.promise);
  });
});

unit test result:

  51959840
    ✓ should do nothing if codeId is equal with curr_id (2884ms)
    ✓ should throw error if codeId is NOT equal with curr_id


  2 passing (3s)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 main.js  |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------

package versions:

"proxyquire": "^2.1.3",
"sinon": "^8.1.1",
"aws-sdk": "^2.817.0",
Tinatinamou answered 25/12, 2020 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.