admin管理员组文章数量:1323524
I am writing tests with jest in which I want to spy on some lodash functions, that I import separately in the module (opposed to importing the whole lodash module as _
), e.g.
/** 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 })
}
The shuffleVert
function shuffles all rows of a matrix, or only those of the specified columns. Because it is difficult to test functions with a random output, to my knowledge, I just want to test if the shuffle and pick function of lodash have been called inside the tested function.
I currently have implemented a working spy procedure in my test module, but I don't think it's conventional or efficient, and I just think there must be a better way to do this...
/* 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)
})
})
I know jest has a spyOn
functionality, but that only appears to work on object methods, thus
import * as lodash from 'lodash'
const shuffleSpy = jest.spyOn(lodash, 'shuffle')
results in the error Cannot spyOn on a primitive value; undefined given
What is generally the best way in jest to spy on methods of a module? Is there a better implementation for doing what I'm trying to achieve? Or is this already the way to go?
I am writing tests with jest in which I want to spy on some lodash functions, that I import separately in the module (opposed to importing the whole lodash module as _
), e.g.
/** 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 })
}
The shuffleVert
function shuffles all rows of a matrix, or only those of the specified columns. Because it is difficult to test functions with a random output, to my knowledge, I just want to test if the shuffle and pick function of lodash have been called inside the tested function.
I currently have implemented a working spy procedure in my test module, but I don't think it's conventional or efficient, and I just think there must be a better way to do this...
/* 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)
})
})
I know jest has a spyOn
functionality, but that only appears to work on object methods, thus
import * as lodash from 'lodash'
const shuffleSpy = jest.spyOn(lodash, 'shuffle')
results in the error Cannot spyOn on a primitive value; undefined given
What is generally the best way in jest to spy on methods of a module? Is there a better implementation for doing what I'm trying to achieve? Or is this already the way to go?
Share Improve this question edited Dec 6, 2018 at 12:59 Daniel Schreij asked Dec 6, 2018 at 10:50 Daniel SchreijDaniel Schreij 7631 gold badge11 silver badges28 bronze badges 5-
Is
lodash
specified inpackage.json
? It looks likelodash
is undefined injest.spyOn(lodash, 'shuffle')
. – Dinesh Pandiyan Commented Dec 6, 2018 at 11:02 - Yes, lodash is present and is used throughout the app. – Daniel Schreij Commented Dec 6, 2018 at 12:58
- Did you ever get this issue resolved? I'm currently struggling with the same problem. – Khaladin Commented Jul 28, 2020 at 19:53
- This is too lang ago so I don't really remember how I tackled this. I think I took a pletely different approach from using jest spies though... – Daniel Schreij Commented Aug 4, 2020 at 9:15
- 1 Does this answer your question? How to spy on a default exported function with Jest? – Xeltor Commented Oct 27, 2021 at 18:56
1 Answer
Reset to default 3Please try this and let me know if it works for you
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);
}
Then if you want to check any other function execution times, just add them to a/that constant and spyOn
them below.
I too don't have a full understanding of this, but from the little I read, the latest versions of JavaScript have this principle called "single source of truth" which is required for some things to work properly.
本文标签: javascriptSpying on module functions in jestStack Overflow
版权声明:本文标题:javascript - Spying on module functions in jest - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742132096a2422207.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论