简体   繁体   English

节点 + 笑话 + mocking 事件处理程序回调

[英]node + jest + mocking event handler callbacks

I have a function in my Node.js code which I am trying to test but I want to mock out processStreamData :我的 Node.js 代码中有一个 function ,我正在尝试测试它,但我想模拟出processStreamData

async functionToTest(stream) {
  // Run some checks on the stream here
  stream.on('data', async (data) => {
    // Run some checks on the data here
    await this.processStreamData(data);
  }).on('finish', () => {
    // Do some processing here
    resolve();
  });
}

async processStreamData(data) {
  ...
}

Here is my test:这是我的测试:

test('functionToTest success', async (testCase) => {
  try {
    let readStream = fs.createReadStream(`${DATA_DIR}/genericCsv.csv`);
    jest.spyOn(myClass, "processStreamData").mockImplementation();

    await expect(myClass.functionToTest(readStream)).resolves.toEqual(undefined);
    await expect(myClass.processStreamData).toBeCalledWith(expect.anything());

    testCase();
  } catch(exception) {
    console.log(exception);
    testCase.fail(new Error(`Test failed${exception}`));
  };
});

It seems like because processStreamData is inside an event handler, the original function (rather than the mock) is called.似乎因为processStreamData在事件处理程序中,所以调用了原始的 function (而不是模拟)。

I've also tried mocking the function via我也试过 mocking function 通过

myClass.processStreamData = jest.fn.mockImplementation()

which didn't work.这没有用。 The original function was still called.原来的 function 仍然被调用。

I've done some googling and am well-aware that jest historically has had limitations around this https://github.com/facebook/jest/issues/207 but does this still apply?我已经进行了一些谷歌搜索,并且很清楚 jest 在历史上对这个https://github.com/facebook/jest/issues/207有限制,但这仍然适用吗? If not, can someone hand-hold me through the process of how I should set up my mock so it can be used?如果没有,有人可以帮助我完成我应该如何设置我的模拟以便可以使用它的过程吗?

Here is a unit test solution:这是一个单元测试解决方案:

index.ts : index.ts

export class SomeClass {
  async functionToTest(stream) {
    // Run some checks on the stream here
    stream
      .on('data', async data => {
        // Run some checks on the data here
        await this.processStreamData(data);
      })
      .on('finish', () => {
        // Do some processing here
        Promise.resolve();
      });
  }

  async processStreamData(data) {
    console.log(data);
  }
}

index.spec.ts : index.spec.ts

import fs, { ReadStream } from 'fs';
import path from 'path';
import { SomeClass } from './';

const myClass = new SomeClass();
const DATA_DIR = './.tmp';

afterEach(() => {
  jest.restoreAllMocks();
});

test('functionToTest success', async () => {
  const readStream: ReadStream = fs.createReadStream(path.resolve(__dirname, `${DATA_DIR}/genericCsv.csv`));
  const events: { [event: string]: (...args: any[]) => void } = {};
  jest.spyOn(readStream, 'on').mockImplementation((event: string, listener: (...args: any[]) => void) => {
    events[event] = listener;
    return readStream;
  });
  jest.spyOn(myClass, 'processStreamData');

  await expect(myClass.functionToTest(readStream)).resolves.toEqual(undefined);
  events.data('fake data');
  expect(myClass.processStreamData).toBeCalledWith('fake data');
});

test('functionToTest finish', async () => {
  const readStream: ReadStream = fs.createReadStream(path.resolve(__dirname, `${DATA_DIR}/genericCsv.csv`));
  const events: { [event: string]: (...args: any[]) => void } = {};
  jest.spyOn(readStream, 'on').mockImplementation((event: string, listener: (...args: any[]) => void) => {
    events[event] = listener;
    return readStream;
  });
  jest.spyOn(Promise, 'resolve');

  await expect(myClass.functionToTest(readStream)).resolves.toEqual(undefined);
  events.finish();
  expect(Promise.resolve).toBeCalledTimes(1);
});

Unit test result with 100% coverage:覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/58244855/index.spec.ts (6.502s)
  ✓ functionToTest success (14ms)
  ✓ functionToTest finish (1ms)

  console.log src/stackoverflow/58244855/index.ts:3320
    fake data

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

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58244855源码: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58244855

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM