У меня есть 2 функции javascript A и B, определенные как показано ниже, и которые предоставляются через другую функцию, называемую API, как показано ниже. Я хочу протестировать функцию A, чтобы узнать, вызывает ли она B или нет.
function A () {
B()
}
function B () {
console.info('B is called')
}
export function API (){
return {
a: A,
b: B
}
}
Я попробовал свои тестовые функции, как показано ниже, но они не работают.
import { API } from './actions-beta'
describe('test A', () => {
test('', () => {
const fn = API()
console.info(fn)
const spy = jest.spyOn(fn, 'b')
fn.a()
expect(spy).toHaveBeenCalled()
})
})
Невозможно проверить, вызывается ли B
так, как написан код.
jest.spyOn
заменяет свойство функции объекта на шпионское.
jest.spyOn(fn, 'b')
заменит свойство b
на объекте fn
на шпион.
fn.a()
вызывает A
, который вызывает B
напрямую, но не вызывает fn.b
, поэтому шпион никогда не вызывается.
A
необходимо вызвать B
используя свойство объекта, которое можно заменить на шпиона во время теста.
При создании шпиона объект обычно является модулем.
Вот почему слежение за экспортируемыми функциями довольно просто, а слежение за неэкспортируемыми функциями довольно сложно, что поднимает важный момент: если функция вызывает неэкспортированную функцию в том же модуле, тогда это просто деталь реализации, которая не видна за пределами модуля, и при подходе к тестированию черного ящика ее не нужно тестировать.
Если вы обнаружите, что B
- это больше, чем деталь реализации, и вы хотите шпионить или заглушить его функциональность, тогда самый простой подход (особенно для этого кода, где экспорт - это функция, которая создает новый объект каждый раз, когда он вызывается) - переместить B
в собственный модуль:
действия-beta.js
import { B } from './lib';
export function A () {
B()
}
export function API (){
return {
a: A,
b: B
}
}
lib.js
export function B () {
console.info('B is called')
}
Тест:
import { API } from './actions-beta'
import * as lib from './lib'; // import the module with B
describe('test A', () => {
test('', () => {
const fn = API()
console.info(fn)
const spy = jest.spyOn(lib, 'B') // spy on B using its module
fn.a()
expect(spy).toHaveBeenCalled() // SUCCESS
})
})