如何测试嵌套的模拟函数

时间:2017-07-05 09:25:28

标签: javascript node.js unit-testing mocking jest

如何在模拟函数内的模拟函数上编写测试?我想测试我的publish模拟函数被调用一次。

jest.mock('amqplib', () => ({
  connect: jest.fn(() => Promise.resolve({
    createChannel: jest.fn(() => Promise.resolve({
      assertExchange: jest.fn(),
      publish: jest.fn(),
    })),
    close: jest.fn(),
  })),
}));

我想测试的实际功能。

export default function (key, data, exchange = 'portal.topic', options = { type: 'topic' }) {
  return amqp.connect(`amqp://${RABBITMQ_USER}:${RABBITMQ_PASS}@${RABBITMQ_URL}:${RABBITMQ_PORT}`).then(conn => {
    conn.createChannel().then((ch) => {
      ch.assertExchange(exchange, options.type, { durable: true });
      ch.publish(exchange, key, Buffer.from(JSON.stringify(data)));
    });
    setTimeout(() => { conn.close(); }, 1000);
  });
}

1 个答案:

答案 0 :(得分:1)

首先,我建议根据您的逻辑从代码中删除setTimeout,并且conn.createChannel方法不会与外部诺言形成诺言链。更改后,单元测试:

index.js

import amqp from 'amqplib';

const RABBITMQ_USER = 'RABBITMQ_USER';
const RABBITMQ_PASS = 'RABBITMQ_PASS';
const RABBITMQ_URL = 'RABBITMQ_URL';
const RABBITMQ_PORT = 'RABBITMQ_PORT';

export default function(key, data, exchange = 'portal.topic', options = { type: 'topic' }) {
  return amqp
    .connect(`amqp://${RABBITMQ_USER}:${RABBITMQ_PASS}@${RABBITMQ_URL}:${RABBITMQ_PORT}`)
    .then((conn) => {
      return conn.createChannel().then((ch) => {
        ch.assertExchange(exchange, options.type, { durable: true });
        ch.publish(exchange, key, Buffer.from(JSON.stringify(data)));
        return conn;
      });
    })
    .then((conn) => conn.close());
}

index.test.js

import createChannel from './';
import amqp from 'amqplib';

describe('44922162', () => {
  afterAll(() => {
    jest.restoreAllMocks();
  });
  it('should create channel correctly', async () => {
    const mCh = { assertExchange: jest.fn(), publish: jest.fn() };
    const mConn = { createChannel: jest.fn().mockResolvedValueOnce(mCh), close: jest.fn() };
    const connectSpy = jest.spyOn(amqp, 'connect').mockResolvedValueOnce(mConn);
    const data = { payload: '123' };
    await createChannel('key', data);
    expect(connectSpy).toBeCalledWith('amqp://RABBITMQ_USER:RABBITMQ_PASS@RABBITMQ_URL:RABBITMQ_PORT');
    expect(mConn.createChannel).toBeCalledTimes(1);
    expect(mCh.assertExchange).toBeCalledWith('portal.topic', 'topic', { durable: true });
    expect(mCh.publish).toBeCalledWith('portal.topic', 'key', Buffer.from(JSON.stringify(data)));
    expect(mConn.close).toBeCalledTimes(1);
  });
});

具有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/44922162/index.test.js (11.008s)
  44922162
    ✓ should create channel correctly (7ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.335s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/44922162