Lays Rodrigues
Lays Rodrigues

Reputation: 105

Jest mock twilio - how to?

I have been using Jest to do my unit tests with node.

I am used to mocking the first level of the modules/functions, but on the challenge to mock Twilio, I am not having so much luck.

I am using the twilio method: client.messages.create, so here I have the twilio client from the constructor require('twilio')(account sid, token), and the first layer is from the object/method(?) messages, and last the third level create, and it's this last guy that I am trying to mock.

I was trying something like this:

jest.mock('twilio', () => {
  const mKnex = {
    messages: jest.fn(),
  };
  return jest.fn(mKnex);
});

However, I am not able to mock the client resolved value, where I get client.message.create is not a function. If I try the above mock plus this client.messages.create.mockReturnValueOnce({sid: "FOO", status: "foo"); I get that cannot read the property create from undefined(messages).

Any tip, post, docs that could give me some luck on this? Thanks

Upvotes: 6

Views: 5552

Answers (2)

Willian
Willian

Reputation: 3405

The solution for this is:

  1. Create a file for Twilio client:
// sms.client.ts

import { Twilio } from 'twilio';

const smsClient = new Twilio(
  'TWILIO-ACCOUNT-SID',
  'TWILIO-TOKEN'
);

export { smsClient };

  1. Then, your service file should look like this:
// sms.service.ts

import { smsClient } from './sms.client';

class SMSService {
  async sendMessage(phoneNumber: string, message: string): Promise<string> {
    const result = await smsClient.messages.create({
      from: '(555) 555-5555',
      to: phoneNumber,
      body: message,
    });

    if (result.status === 'failed') {
      throw new Error(`Failed to send sms message. Error Code: ${result.errorCode} / Error Message: ${result.errorMessage}`);
    }

    return result.sid;
  }
}

export const smsService = new SMSService();

  1. Last but not least, your spec/test file needs to mock the client file. E.g.
// sms.service.spec.ts

import { MessageInstance, MessageListInstance } from 'twilio/lib/rest/api/v2010/account/message';
import { smsClient } from './sms.client';
import { smsService } from './sms.service';

// mock the client file
jest.mock('./sms.client');

// fixture
const smsMessageResultMock: Partial<MessageInstance> = {
  status: 'sent',
  sid: 'AC-lorem-ipsum',
  errorCode: undefined,
  errorMessage: undefined,
};

describe('SMS Service', () => {
  beforeEach(() => {
    // stubs
    const message: Partial<MessageListInstance> = {
      create: jest.fn().mockResolvedValue({ ...smsMessageResultMock })
    };
    smsClient['messages'] = message as MessageListInstance;
  });

  it('Should throw error if response message fails', async () => {
    // stubs
    const smsMessageMock = {
      ...smsMessageResultMock,
      status: 'failed',
      errorCode: 123,
      errorMessage: 'lorem-ipsum'
    };
    smsClient.messages.create = jest.fn().mockResolvedValue({ ...smsMessageMock });

    await expect(
      smsService.sendMessage('(555) 555-5555', 'lorem-ipsum')
    ).rejects.toThrowError(`Failed to send sms message. Error Code: ${smsMessageMock.errorCode} / Error Message: ${smsMessageMock.errorMessage}`);
  });

  describe('Send Message', () => {
    it('Should succeed when posting the message', async () => {
      const resultPromise = smsService.sendMessage('(555) 555-5555', 'lorem-ipsum');
      await expect(resultPromise).resolves.not.toThrowError(Error);
      expect(await resultPromise).toEqual(smsMessageResultMock.sid);
    });
  });
});

Upvotes: 3

Collin
Collin

Reputation: 409

I've found a solution. It's still calling the endpoint, but for each twilio account, you get a test SID and Token, I used this one so it does not send a sms when testing with this:

if (process.env.NODE_ENV !== 'test') {
    client = require('twilio')(accountSid, authToken)
    listener = app.listen(3010, function(){
        console.log('Ready on port %d', listener.address().port)
    })
}else{
    client = require('twilio')(testSid, testToken)
}

Upvotes: -2

Related Questions