开玩笑的嘲笑twilio-如何?

时间:2020-06-30 00:27:45

标签: unit-testing jestjs twilio

我一直在使用Jest对node进行单元测试。

我习惯于嘲笑模块/函数的第一级,但是在模仿Twilio的挑战中,我没有那么幸运。

我正在使用twilio方法:client.messages.create,所以这里有来自构造函数require('twilio')(account sid, token)的twilio客户端,第一层是来自对象/方法(?)messages ,最后是第三级create,这就是我要嘲笑的最后一个家伙。

我正在尝试这样的事情:

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

但是,我无法模拟得到client的{​​{1}}解析值。 如果尝试上面的模拟加上此client.message.create is not a function,我将无法从client.messages.create.mockReturnValueOnce({sid: "FOO", status: "foo");(消息)读取属性create

任何提示,帖子,文档都可以给我带来一些运气吗? 谢谢

2 个答案:

答案 0 :(得分:0)

我找到了解决方案。它仍然在调用端点,但是对于每个twilio帐户,您都会得到一个测试SID和令牌,我使用了这个,因此在对此进行测试时它不会发送短信:

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)
}

答案 1 :(得分:0)

对此的解决方案是:

  1. 为 Twilio 客户端创建文件:
// sms.client.ts

import { Twilio } from 'twilio';

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

export { smsClient };

  1. 然后,您的服务文件应如下所示:
// 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. 最后但并非最不重要的一点是,您的规范/测试文件需要模拟客户端文件。例如
// 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);
    });
  });
});

相关问题