Home > Enterprise >  How to mock the return value of messages.create() method from twilio-node using sinon js/loopback te
How to mock the return value of messages.create() method from twilio-node using sinon js/loopback te

Time:10-19

I'm trying to mock the return value of messages.create() method from twilio-node library.

Since the create method resides inside the interface called messages, i can't directly mock the return value of create method.

My Unit test:

import {
  createStubInstance,
  StubbedInstanceWithSinonAccessor,
} from '@loopback/testlab';
import sinon from 'sinon';
import {Twilio} from '../../../../clients/whatsapp-sms-clients/twilio.whatsapp-sms-clients';
import twilio from 'twilio';

describe('Twilio client (UnitTest)', () => {
  let twilioMock: StubbedInstanceWithSinonAccessor<twilio.Twilio>;
  let logger: StubbedInstanceWithSinonAccessor<LoggingService>;
  let twilioClient: Twilio;

  beforeEach(() => {
    twilioMock = createStubInstance(twilio.Twilio);
    logger = createStubInstance(LoggingService);
    twilioClient = new Twilio(twilioMock, logger);
  });

  it('should create the message', async () => {
    twilioMock.stubs.messages.create.resolves({
      // mocked value
    });
  });
});

Thanks in advance.

CodePudding user response:

Twilio developer evangelist here.

I've not worked with testlab/sinon like this before, but I think I have an idea of what you need to do, if not the right syntax.

You'd need to stub the response to twilioMock.messages to return an object that has a create property that is a stubbed function that resolves to the result you want. Something like this might work, or at least set you on the right track:

  it('should create the message', async () => {
    // Create stub for response to create method:
    const createStub = sinon.stub().resolves({
      // mocked value
    });
    // Stub the value "messages" to return an object that has a create property with the above stub:
    twilioMock.stubs.messages.value({ 
      create: createStub
    });

    // Rest of the test script
  });

Edit

OK, using value above didn't work. I tried again. This version strips out your custom Twilio wrapper from the example and just calls things directly on the Twilio client stub itself. Hopefully you can use this as inspiration to work it into your tests.

What I realised is that twilioClient.messages is a getter and is dynamically defined. So, I directly stubbed the result on the stub client.

import {
  createStubInstance,
  StubbedInstanceWithSinonAccessor,
} from "@loopback/testlab";
import sinon from "sinon";
import { Twilio } from "twilio";

describe("Twilio client (UnitTest)", () => {
  let twilioMock: StubbedInstanceWithSinonAccessor<Twilio>;

  beforeEach(() => {
    twilioMock = createStubInstance(Twilio);
  });

  it("should create the message", async () => {
    const createStub = sinon.stub().resolves({
      sid: "SM1234567",
    });
    sinon.stub(twilioMock, "messages").get(() => ({
      create: createStub,
    }));
    const message = await twilioMock.messages.create({
      to: "blah",
      from: "blah",
      body: "hello",
    });
    expect(message.sid).toEqual("SM1234567");
  });
});

The above test passes for me in my setup.

  • Related