簡體   English   中英

如何在 TS 中模擬 childprocess.exec

[英]How to mock childprocess.exec in TS

export function executeCommandPromise(file: string, command: string) {
  return new Promise((resolve, reject) => {
    exec(command, { cwd: `${file}` }, (error: ExecException | null, stdout: string, stderr: string) => {
      if (error) {
        console.warn(error);
        reject(error);
      }
      resolve(capRunnable);
    });
  });
}

我想創建一個測試,它將 exec 命令存根 exec 被調用到回調函數的問題,我想控制標准輸出

我試圖做類似的事情

let sandbox = sinon.sandbox.create();

let event= new events.EventEmitter();


sandbox.stub(child_process, 'exec').returns(event);

但它沒有用,我不知道如何將結果返回到標准輸出

這是單元測試解決方案:

index.ts

import cp, { ExecException } from 'child_process';

const capRunnable = 'capRunnable';

export function executeCommandPromise(file: string, command: string) {
  return new Promise((resolve, reject) => {
    cp.exec(command, { cwd: `${file}` }, (error: ExecException | null, stdout: string, stderr: string) => {
      if (error) {
        console.warn(error);
        reject(error);
      }
      resolve(capRunnable);
    });
  });
}

index.spec.ts

import { executeCommandPromise } from './';
import cp, { ChildProcess, ExecException } from 'child_process';

describe('executeCommandPromise', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  test('should exec command correctly', async () => {
    let execCallback: (error: ExecException | null, stdout: string, stderr: string) => void;
    jest
      .spyOn(cp, 'exec')
      .mockImplementation(function(
        this: ChildProcess,
        command: string,
        options: any,
        callback?: (error: ExecException | null, stdout: string, stderr: string) => void
      ): ChildProcess {
        if (callback) {
          execCallback = callback;
        }
        return this;
      });
    const actualValue = executeCommandPromise('somefile', 'ls -a');
    execCallback!(null, '', '');
    await expect(actualValue).resolves.toBe('capRunnable');
    expect(cp.exec).toBeCalledWith('ls -a', { cwd: 'somefile' }, execCallback!);
  });

  test('should throw error when exec command failed', async () => {
    let execCallback: (error: ExecException | null, stdout: string, stderr: string) => void;
    jest
      .spyOn(cp, 'exec')
      .mockImplementation(function(
        this: ChildProcess,
        command: string,
        options: any,
        callback?: (error: ExecException | null, stdout: string, stderr: string) => void
      ): ChildProcess {
        if (callback) {
          execCallback = callback;
        }
        return this;
      });
    const actualValue = executeCommandPromise('somefile', 'ls -a');
    execCallback!(new Error('some error happened'), '', '');
    await expect(actualValue).rejects.toThrowError('some error happened');
    expect(cp.exec).toBeCalledWith('ls -a', { cwd: 'somefile' }, execCallback!);
  });
});

覆蓋率 100% 的單元測試結果:

 PASS  src/stackoverflow/57589104/index.spec.ts (8.518s)
  executeCommandPromise
    ✓ should exec command correctly (15ms)
    ✓ should throw error when exec command failed (10ms)

  console.warn src/stackoverflow/57589104/index.ts:469
    Error: some error happened
        at /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:45:19
        at step (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:33:23)
        at Object.next (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:14:53)
        at /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:8:71
        at new Promise (<anonymous>)
        at Object.<anonymous>.__awaiter (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:4:12)
        at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/57589104/index.spec.ts:29:55)
        at Object.asyncJestTest (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
        at resolve (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
        at new Promise (<anonymous>)
        at mapper (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
        at promise.then (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:73:41)
        at process._tickCallback (internal/process/next_tick.js:68:7)

----------|----------|----------|----------|----------|-------------------|
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:        10.086s

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM