开玩笑地监视模块功能

Dan*_*eij 10 javascript unit-testing lodash jestjs es6-modules

我正在用玩笑编写测试,其中我想监视一些 lodash 函数,我在模块中单独导入这些函数(而不是将整个 lodash 模块导入为_),例如

/** matrix.js **/
import shuffle from 'lodash/shuffle'
import pick from 'lodash/pick'

// ...

/**
 * Shuffles the order of the rows in the matrix. If a column/variable name
 * is specified, only the rows in this column are shuffled.
 *
 * @export
 * @param {array} matrix The matrix to be shuffled
 * @param {array} columns  Array containing the variable/column to be shuffled
 * @returns {array}
 */
export function shuffleVert (matrix, columns) {
  if (typeof (columns) === 'undefined' || (isArray(columns) && columns.length === 0)) {
    return shuffle(matrix)
  } else if (!isArray(columns)) {
    throw new TypeError('Invalid argument for columns specified to shuffleVert. Expects an array containing column names')
  } else {
    let grouped = unstack(matrix)
    let cols = pick(grouped, columns)
    cols = Object.entries(cols).reduce((prev, [key, values]) => {
      prev[key] = shuffle(values)
      return prev
    }, {})
    return stack({ ...grouped, ...cols })
 }
Run Code Online (Sandbox Code Playgroud)

shuffleVert函数会打乱矩阵的所有行,或仅打乱指定列的行。因为很难用随机输出来测试函数,据我所知,我只想测试被测试的函数内部是否调用了lodash的shuffle和pick函数。

我目前已经在我的测试模块中实现了一个工作间谍程序,但我认为它不是传统的或有效的,而且我只是认为必须有更好的方法来做到这一点......

/* matrix.test.js */
import {
  shuffleVert,
} from 'matrix'

/** Generate a mock functions to spy on lodash */
const mockShuffle = jest.fn()
jest.mock('lodash/shuffle', () => a => {
  const shuffle = jest.requireActual('lodash/shuffle')
  mockShuffle()
  return shuffle(a)
})

const mockPick = jest.fn()
jest.mock('lodash/pick', () => (a, b) => {
  const pick = jest.requireActual('lodash/pick')
  mockPick()
  return pick(a, b)
})

describe('reverseRows', () => {
  let srcMatrix
  beforeEach(() => {
    srcMatrix = [
      { number: 1, word: 'one' },
      { number: 2, word: 'two' },
      { number: 3, word: 'three' }
    ]
    mockShuffle.mockClear()
    mockPick.mockClear()
  })

  it('should shuffle the rows of the entire matrix with no argument for columns', () => {
    shuffleVert(srcMatrix)
    // 2 is weird, but seems correct.
    // It appears the shuffle function calls itself recursively
    expect(mockShuffle).toHaveBeenCalledTimes(2)
  })

  it('should only shuffle the rows of columns that were specified', () => {
    shuffleVert(srcMatrix, ['word'])
    expect(mockShuffle).toHaveBeenCalledTimes(2)
    expect(mockPick).toHaveBeenCalledTimes(2)
  })
})
Run Code Online (Sandbox Code Playgroud)

我知道 jest 有一个spyOn功能,但似乎只适用于对象方法,因此

import * as lodash from 'lodash'
const shuffleSpy = jest.spyOn(lodash, 'shuffle')
Run Code Online (Sandbox Code Playgroud)

结果出现错误Cannot spyOn on a primitive value; undefined given

开玩笑地说,监视模块方法的最佳方法是什么?是否有更好的实现来实现我想要实现的目标?或者这已经是要走的路了吗?

Tir*_*ium 3

请尝试一下,让我知道它是否适合您

import { shuffleVert } from 'matrix';
const shuffleVertRef = {
    shuffleVert
};
let spyShuffleVert;

beforeEach(() => {
    spyShuffleVert = jest.spyOn(shuffleVertRef, "shuffleVert");
}

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

it('should shuffle the rows of the entire matrix with no argument for columns', () = {
    let srcMatrix = [
        { number: 1, word: 'one' },
        { number: 2, word: 'two' },
        { number: 3, word: 'three' }
    ];

    shuffleVert(srcMatrix);
    expect(spyShuffleVert).toHaveBeenCalledTimes(2);
}
Run Code Online (Sandbox Code Playgroud)

然后,如果您想检查任何其他函数的执行时间,只需将它们添加到/该常量和spyOn下面。

我对此也没有完全理解,但从我读到的一点来看,最新版本的 JavaScript 有一个称为“单一事实来源”的原则,这是某些事情正常工作所必需的。

  • 另一种方法是将前 2 条语句替换为“import * as shuffleVertRef from 'matrix';” (3认同)