Search code examples
javascriptnode.jsaws-lambdasinonsinon-chai

Sinon cannot stub non-existent own property 'function'


I am trying to mock a module Database so that its getRecordDetails() member function would always return some fixed data. See below:

handler.js

const sinon = require("sinon");
const Database = require("../../lib/Database");
const database= new Database();

module.exports = {
  handler(event, context, callback) {
    event.Records.forEach(record=> {
       const recordDetails = database.getRecordDetails(record);
       // Do something with recordDetails
    });
  }
}
..

test.js

const sinon = require("sinon");
const db= require("../../lib/Database");
const lamdbda = require("../../lib/lambda.js");

describe("Test suite", () => {
  it("invoke lambda",  done => {
    lambda.handler(data, {}, (err, data) => {
      sinon.stub(db, "getRecordDetails").withArgs(sinon.match.any).returns("{id: 1}");
      ...
    }
  }

}

database.js

class Database {
  constructor() {
    this.dynamdbClient = new AWS.DynamoDB.DocumentClient();
  }

  getRecordDetails(record) {
    const param = {
      TableName: ..
      Key: {
        uuid: record.uuid
        ...
     }
    }
    const dbRecord = await docClient.get(params).promise();
    return mapToRecordDetails(dbRecord); // new object mostly 1-1 mappings.
  }

}

But I get:

TypeError: Cannot stub non-existent own property getRecordDetails What am I doing wrong?


Solution

  • The getRecordDetails method is an instance method of your Database class. Try sinon.stub(Database.prototype, 'getRecordDetails').

    E.g.

    handle.js:

    const Database = require('./database');
    const database = new Database();
    
    module.exports = {
      handler(event, context, callback) {
        event.Records.forEach((record) => {
          const recordDetails = database.getRecordDetails(record);
          console.log("🚀 ~ file: handler.js:8 ~ event.Records.forEach ~ recordDetails:", recordDetails)
        });
      },
    };
    

    database.js:

    const AWS = require('aws-sdk');
    
    class Database {
      constructor() {
        this.dynamdbClient = new AWS.DynamoDB.DocumentClient();
      }
    
      async getRecordDetails(record) {
        const param = {
          TableName: 'a',
          Key: {
            uuid: record.uuid,
          },
        };
        return docClient.get(params).promise();
      }
    }
    
    module.exports = Database;
    

    handler.test.js:

    const sinon = require('sinon');
    const Database = require('./database');
    const lamdbda = require('./handler.js');
    
    describe('Test suite', () => {
      it('invoke lambda', () => {
        sinon.stub(Database.prototype, 'getRecordDetails').returns('{id: 1}');
        lamdbda.handler({ Records: [1] }, {}, (err, data) => {});
      });
    });
    

    Test result:

      Test suite
    🚀 ~ file: handler.js:8 ~ event.Records.forEach ~ recordDetails: {id: 1}
        ✓ invoke lambda
    
    
      1 passing (4ms)