如何测试嵌套模拟函数

问题描述 投票:0回答:2

如何在模拟函数内编写对模拟函数的测试?我想测试我的

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);
  });
}
javascript node.js unit-testing mocking jestjs
2个回答
3
投票

首先,我建议根据您的逻辑从代码中删除

setTimeout
,并且
conn.createChannel
方法不会与外部promise形成promise链。更改后,单元测试:

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


0
投票

我知道这可能有点过时,因为这个问题是在 2020 年提出的,但我只是在搜索时偶然发现了这个,所以为什么不给出我自己的解决方案。

所以,我的写法有点不同,因为我不希望我的测试套件在测试时连接到真正的 RabbitMQ 服务器。

rabbitmq.wrapper.ts

export const rabbitmqWrapper = {
   connect: jest.fn().mockImplementation(()=>this),
   connection: {
      createChannel: jest.fn().mockImplementation(()=>this),
      assertExchange: jest.fn().mockImplementation((exchange: string, type: string, options: any) => {
          console.log(exchange, type, options);
          return this;
      }),
      publish: jest.fn().mockImplementation((exchange: string, routingKey: string, content: Buffer, options: any) => {
          console.log(exchange, routingKey, options);
          return true;
      })
   }
};

然后在我的测试文件中

index.test.js

import { rabbitmqWrapper } from "./rabbitmq.wrapper";
it(`Returns 201 on successful signup`, async ()=>{

    {{Peform your normal test here}}

    expect((await rabbitmqWrapper.connection.createChannel()).publish).toHaveBeenCalled();
}, 20000);

希望这对其他人有帮助

© www.soinside.com 2019 - 2024. All rights reserved.