mbr
mbr

Reputation: 923

stubbing class and methods using sinon stub

I need help in stubbing using sinon msk client functions connect() and send() or sendmessage(). Tried multiple ways but it still invokes the actual function. Please help

Here code snippets in the files.

index.js

var KafkaConnection = require('./mskclient');
                var kafkaObj = new KafkaConnection(key.User, key.Secret);
            var res = await kafkaObj.connectProducer(event.body);

mskclient.js

class KafkaConnection {
  constructor(user, secret) {
    this.connection = new Kafka({
      authenticationTimeout: 5000,
      clientId: client_id,
      brokers: brokerlist.split(','),
      ssl: true,
      sasl: {
        mechanism: 'scram-sha-512',
        username: user,
        password: secret,
      },
    });
    this.producer = null;
  }

  async sendMessage(msgObj) {
    console.log('sendMessage');
    this.producer = this.producer || this.connection.producer();
    await this.producer.connect();
    await this.producer.send(msgObj);
  }

  async disconnect() {
    this.producer && (await this.producer.disconnect());
  }

  async connectProducer(event) {
    try {
      log.info('Sending Message');
      console.log('connectProducer');

      await this.sendMessage({
        topic: process.env.TOPIC_NAME,
        acks: 1,
        messages: [
          {
            key: 'test-key',
            value: JSON.stringify(event),
          },
        ],
      });
      await this.disconnect();
      log.info('Successfully sent message');
      return 0;
    } catch (e) {
      log.info('Message not sent to kafka..');
      log.error(e);
      await this.disconnect();
      return 1;
    }
  }
}

module.exports = KafkaConnection;

so far I tried the following but both of them is getting called kafka actuall function and not stubs

approach #1

const service = require('../index');
const KafkaConnection = require('../mskclient');

var kafkaObj = sinon.createStubInstance(KafkaConnection);

var res1 = service.handler(event).then(function () {
                       done();
                }).catch((error) => {
                    done();
                })

approach #2

const service = require('../index');
const KafkaConnection = require('../mskclient');

//var kafkaObj = sinon.createStubInstance(KafkaConnection);
   SMSStub = sinon.stub(KafkaConnection.prototype, 'KafkaConnection').callsFake(() => {
                return 1
            });

var res1 = service.handler(event).then(function () {
                       done();
                }).catch((error) => {
                    done();
                })

Upvotes: 1

Views: 3171

Answers (2)

seanplwong
seanplwong

Reputation: 1091

First, service on its own import connection class independently.

const service = require('../index'); // <-- import '../mskclient' and create obj
const KafkaConnection = require('../mskclient');

Even if you swap them

const KafkaConnection = require('../mskclient');

const kafkaObj = sinon.createStubInstance(KafkaConnection);

const service = require('../index'); // <-- it is still importing the original mskclient

From https://sinonjs.org/how-to/stub-dependency/, if you really want to stub the dependencies, you will have to export a mutable object:

// mskclient.js
module.exports = {
  KafkaConnection: class KafkaConnection {},
};

// service.js
const mod = require('./mskclient');

module.exports = function run() {
  const conn = new mod.KafkaConnection();
  conn.doSomething();
}

But if you use jest, you could

jest.mock('../mskclient');
// or
jest.mock('../mskclient', () => jest.fn(() => ({
  connectProducer: jest.fn(),
})));

const service = require('../index'); // <-- import '../mskclient' and create obj
const KafkaConnection = require('../mskclient');

// es6
import service from '../';
import KafkaConnection from '../mskclient';

jest.mock('../mskclient', () => jest.fn(() => ({
  connectProducer: jest.fn(),
})));

SEE: https://jestjs.io/docs/next/es6-class-mocks#automatic-mock

Upvotes: 1

zishone
zishone

Reputation: 1244

Hello based on my understanding of your question, I think this is what you are looking for:

sinon.stub(KafkaConnection.prototype, 'connectProducer').callsFake(() => {
  return 1;
})
sinon.stub(KafkaConnection.prototype, 'sendMessage').callsFake(() => {})

The second parameter of sinon.stub should be the name of the function that you would like to mock.

Upvotes: 1

Related Questions