Jestjs как проверить функцию, вызываемую внутри другой функции


Для тестирования я использую jest и react-test-renderer. Это должно быть просто проверить, однако мне трудно найти правильный пример. Я попытался сделать что-то вроде этого (в общем, я храню функции в отдельных файлах):

Utils.js

export const childFunction = () => 'something';    
const parentFunction = () => childFunction();
export default parentFunction;

Utils.тест.js

import parentFunction from './utils.js';


it('childFunction should be called', () => {
 const childFunction = jest.fn();
 parentFunction();
 expect(childFunction).toBeCalled();
})

Фрагмент const childFunction = jest.fn (); определенно не будет работать. Во время вызова тело родительской функции заботится только о своем собственном объеме. Но это также не будет работать, если я импортирую childFunction и сделайте шутку.mock (childFunction) , потому что шутка.макету нужна строка, url-адрес модуля, а не сама функция.

Приведенный выше пример не работает, и я ищу альтернативу. Однако это работает после компонента Shallowrender React. И я хотел бы добиться аналогичного поведения с функцией, вложенной в другую функцию.

class Component extends React.Component {
 componentDidMount() {parentFunction()}
 render() {...}
}

const renderer = new ShallowRenderer();
describe("testing parentFunction", () => {
  renderer.render(<Component/>);
  it("parentFunction should be called", () => {
    expect(parentFunction).toBeCalled();
  });
});
2 2

2 ответа:

Невозможно следить за вызовом функции, если функция не вызывается как метод объекта.

Как объяснено в Этот ответ, из-за того, как работают модули ES, можно шпионить или имитировать функцию, только если она была экспортирована из модуля и используется в другом модуле. Таким образом, он может быть подсмотрен на объекте модуля * или высмеян с помощью jest.mock.

Если это не так, его следует проверить косвенно:

expect(childFunction()).toBe('something');
expect(parentFunction()).toBe('something');

Не уверен, что это поможет, но это может дать вам идеи.

Во-первых, приведенный выше пример:

// this needs to be stubbed
// const childFunction = () => 'something';
const childFunction = jest.fn();

const parentFunction = () => childFunction();

it('childFunction should be called', () => {
    parentFunction();
    expect(childFunction).toHaveBeenCalled();
}

Это несколько надуманный пример, поскольку маловероятно, что childFunction экспортируется, поэтому вы не можете получить ссылку на него и подделать/заглушить его.

Один обходной путь, который вы должны были бы переместить его в свой собственный метод

class Component extends React.Component {
  componentDidMount() {
    this.parentFunction();
  }
  parentFunction() {
    parentFunction(); // from elsewhere
  }
  render() {...}
}
Это позволяет создать прокол и шпионить за компонентом proto.

Например

const spy = jest.spyOn(Component.prototype, 'parentFunction');

// ... mount so lifecycle runs... 
expect(spy).toHaveBeenCalled(); // and clear the spy mocks after!

Может быть, лучше поиздеваться над модулем

Например у вас есть utils.js используется вашим компонентом, который делает:

export function parentFunction(){ console.log('parent'); }

Компонент.js делает:

import { parentFunction } from './utils';

Вы могли бы в своих тестах сделать:

const utils = require('./utils');
utils.parentFunction = jest.fn();
import Component from './component';
// later
expect(utils.parentFunction).toHaveBeenCalled();

Как вы можете видеть, есть много возможных способов пойти, хотя я не уверен в значении этого теста, вы, вероятно, должны проверить выход / функциональность компонента, а не то, что он вызвал, имея что-то запущенное на componentDidMount является заданным и только сломается, если кто-то преобразуется в функциональный или изменяет имя жизненного цикла.