Recommand · October 27, 2021 0

TypeError: stub expected to yield, but no callback was passed. Received [[object Object]] while using sinon to mock a dynamodb get call

I have a simple lambda function which makes a get call to the dynamodb. I am trying to mock this using sinon and am stuck with an error.

app.js

var AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});

async function run(){
    const dynamoDB = new AWS.DynamoDB.DocumentClient();
    const params = {
        TableName: 'employees',
        Key: {
            name: "naxi"
        }
    };
    const result = await dynamoDB.get(params).promise();
    if (result.Item) {
        return result.Item;
    } else {
        return { error: 'Task not found.' };
    }
}

module.exports = {
    run
  }

index.spec.js

const sinon = require('sinon');
const assert = require('assert');
const proxyquire = require('proxyquire');

describe('Test Suite', () => {
  let mut;
  let clientStub;

  before(() => {
    clientStub = {
      get: sinon.stub()
    }

    const awsStub = {
      DynamoDB: {
        DocumentClient: class {
          constructor() {
            return clientStub;
          }
        }
      }
    }

    mut = proxyquire('../app.js', {
      'aws-sdk': awsStub
    })
  });

  it('should get random data!', async () => {
    const expectedData = "neeraj";

    clientStub.get.yields(null, expectedData);

    const data = await mut.run();

    sinon.assert.callCount(clientStub.get, 1);
    assert.strictEqual(data, expectedData);
  });
})

Package.json

"scripts": {
    "test": "mocha ../**/*spec.js --recursive --timeout 10000"
  }

Once I run the test script, I receive the below error.

TypeError: stub expected to yield, but no callback was passed. Received [[object Object]]

Can anyone please tell me what am I missing here ?

this is how i test my code using supertest package and jest.

In my backend, I am making a post request to send some data. Ofcourse you can skip as per your need

let sandbox;
describe('Test', () => {
  beforeEach(() => {
    sandbox = sinon.createSandbox();
   // process.env.redirectBaseUrl = 'http://xxxx/'; // if you want to set
  });
  afterEach(() => {
    delete process.env.redirectBaseUrl;
    sandbox.restore();
  });
  test('should return converted url', async () => {
    const data = {
      Item: {
        convertedUrl: 'abc',
      },
    };

    sandbox
      .stub(AWS.DynamoDB.DocumentClient.prototype, 'get')
      .returns({ promise: () => data });

    const app = require('../app');
    const response = await request(app)
      .post('/users/anon-user/urls')
      .send({ originalUrl: 'https://google.com' });
    expect(response.body).toMatchObject({ convertedUrl: 'abc' });

    expect(response.statusCode).toBe(201);
  });
 })

Below is how I made it work.

const sinon = require('sinon');
const assert = require('assert');
const proxyquire = require('proxyquire');
var AWS = require('aws-sdk');

let sandbox;

describe('Test', () => {
    beforeEach(() => {
        sandbox = sinon.createSandbox();
      });
    
    afterEach(() => {
        sandbox.restore();
    });

    it('should return something', async () => {

        const data = {
            Item: {
              convertedUrl: 'abc',
            }
          };

        sandbox
        .stub(AWS.DynamoDB.DocumentClient.prototype, 'get')
        .returns({ promise: () => data });

        const app = require('../app');
        const result = await app.run();
        assert.strictEqual(result, data);
    });
});