簡體   English   中英

使用 jest 使用鏈式方法默認模擬節點外部模塊

[英]Mock node external module default with chained method using jest

在我們的節點 CLI 中,我們有一個簡單的方法:

'use strict';

const ora = require('ora');

module.exports = function startSpinner({ textOnStart, color, spinnerType }) {
  const spinner = ora({
    text: textOnStart,
    color: color || 'cyan',
    spinner: spinnerType || ''
  }).start();
};

我們嘗試使用 jest 來測試這種方法。 我們有兩個測試要實現:

  • 測試已使用正確的對象參數調用 ora
  • 測試方法start()之后被調用

話雖如此,我們無法正確模擬ora模塊。

ora是第三方,基本構造如下:

class Ora {
    constructor(options){}
    start(){ }
}

const oraFactory = function (opts) {
    return new Ora(opts);
};

module.exports = oraFactory;
module.exports.default = oraFactory;

我們正在尋找一種模擬 ora 的方法。

我們嘗試使用自動模擬:

const ora = require('ora');

jest.mock('ora');

const startSpinner = require('./startSpinner');

describe('startSpinner', () => {
  beforeEach(() => {
    startSpinner({});
  });

  describe('ora', () => {
    it('should call ora', () => {
      expect(ora).toHaveBeenCalled();
    });

    it('should call ora start', () => {
      expect(ora.start).toHaveBeenCalled();
    });
  });
});

但兩個測試分別失敗:

匹配器錯誤:接收的值必須是模擬或間諜函數

Received has type: function Received has value: [Function oraFactory]

匹配器錯誤:接收的值必須是模擬或間諜函數

Received has value: undefined

我們嘗試使用自定義模擬:

const ora = require('ora');

jest.mock('ora', () => {
  return jest.fn().mockImplementation(() => {
    return { start: jest.fn() };
  });
});

它最終得到相同的結果。

我們甚至嘗試將我們的測試轉換為打字稿,然后使用:

import * as ora from 'ora';

const startMock = jest.fn();
jest.mock('ora', () => {
  return jest.fn().mockImplementation(() => {
    return { start: startMock };
  });
});

然后我們能夠成功地測試ora被調用。 但是我們最終遇到了expect(ora.start).toHaveBeenCalled();的錯誤expect(ora.start).toHaveBeenCalled(); 甚至expect((ora as any).start).toHaveBeenCalled();

錯誤 TS2339:屬性 'start' 在類型 'typeof import("/Users/Dev/cli/node_modules/ora/index")' 上不存在。

肯定是因為ora的類型定義是export default function ora(options?: Options | string): Ora;

那么如何在 jest 的節點測試環境中模擬像 ora 這樣的第三方?

你有幾個選擇:


你可以像這樣模擬ora

jest.mock('ora', () => {
  const start = jest.fn();
  const result = { start };
  return jest.fn(() => result);
});

...然后調用ora獲取它返回的對象(因為它總是返回相同的對象)並使用該對象訪問start

it('should call ora start', () => {
  const result = ora();
  expect(result.start).toHaveBeenCalled();  // Success!
});

或者,如果您願意,您可以將start mock 作為屬性附加到ora mock 作為在測試期間訪問它的一種簡單方法,如下所示:

const ora = require('ora');

jest.mock('ora', () => {
  const start = jest.fn();
  const result = { start };
  const ora = jest.fn(() => result);
  ora.start = start;  // attach the start mock to ora
  return ora;
});

const startSpinner = require('./startSpinner');

describe('startSpinner', () => {
  beforeEach(() => {
    startSpinner({});
  });

  describe('ora', () => {
    it('should call ora', () => {
      expect(ora).toHaveBeenCalled();  // Success!
    });

    it('should call ora start', () => {
      expect(ora.start).toHaveBeenCalled();  // Success!
    });
  });
});

暫無
暫無

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

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