如何使用Jest测试异步函数中的函数参数

时间:2020-09-09 23:29:28

标签: typescript unit-testing jestjs

我具有以下功能

export const executeCommand = async (
  command: string
): Promise<{ output: string; error: string }> => {
  let output = "";
  let error = "";

  const options: exec.ExecOptions = {
    silent: true,
    listeners: {
      stdout: (data: Buffer) => {
        output += data.toString();
      },
      stderr: (data: Buffer) => {
        error += data.toString();
      },
    },
  };
  await exec.exec(command, null, options);

  return { output, error };
};

我正在尝试测试stdoutstderr的功能,但是不能。我目前的测试看起来像这样

it(`should return the command output`, async () => {
  const stdOutBuffer: Buffer = new Buffer('The is some output');
  const {output} = await utils.executeCommand('');
  const stdOut = execMock.mock.calls[0][2].listeners.stdout;
  stdOut(stdOutBuffer);
  expect(output).toEqual('The is some output');
});

测试失败,并显示以下内容

    Expected: "The is some output"
    Received: ""

我在做什么错了?

1 个答案:

答案 0 :(得分:1)

单元测试解决方案:

index.ts

import * as exec from './exec';

export const executeCommand = async (command: string): Promise<{ output: string; error: string }> => {
  let output = '';
  let error = '';

  const options: exec.ExecOptions = {
    silent: true,
    listeners: {
      stdout: (data: Buffer) => {
        output += data.toString();
      },
      stderr: (data: Buffer) => {
        error += data.toString();
      },
    },
  };
  await exec.exec(command, null, options);

  return { output, error };
};

exec.ts

export interface ExecOptions {}
export const exec = async (command, _, options): Promise<void> => {};

index.test.ts

import * as utils from './';
import * as exec from './exec';
import { mocked } from 'ts-jest/utils';

jest.mock('./exec');

describe('63820836', () => {
  it(`should return the command output`, async () => {
    const stdOutBuffer: Buffer = new Buffer('The is some output');
    let optionsRef;
    mocked(exec.exec).mockImplementationOnce(async (command, _, options) => {
      optionsRef = options;
      options.listeners.stdout(stdOutBuffer);
    });
    const { output } = await utils.executeCommand('');
    expect(output).toEqual('The is some output');
    expect(exec.exec).toBeCalledWith('', null, optionsRef);
  });

  it('should return the command error', async () => {
    const stdErrBuffer: Buffer = new Buffer('This is some error');
    let optionsRef;
    mocked(exec.exec).mockImplementationOnce(async (command, _, options) => {
      optionsRef = options;
      options.listeners.stderr(stdErrBuffer);
    });
    const { error } = await utils.executeCommand('');
    expect(error).toEqual('This is some error');
    expect(exec.exec).toBeCalledWith('', null, optionsRef);
  });
});

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

 PASS  src/stackoverflow/63820836/index.test.ts (11.776s)
  63820836
    ✓ should return the command output (9ms)
    ✓ should return the command error (1ms)

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

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