Jest.js如何测试另一个函数内部被调用的函数

时间:2018-10-04 15:25:16

标签: javascript reactjs jestjs react-test-renderer

对于测试,我使用jest和react-test-renderer。测试应该很简单,但是我很难找到合适的例子。我试图做这样的事情(通常我将功能保存在单独的文件中):

utils.js

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

utils.test.js

import parentFunction from './utils.js';


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

片段 const childFunction = jest.fn(); 完全无效。调用时,parentFunction的主体仅关心其自身的作用域。但是,如果我导入childFunction并执行 jest.mock(childFunction),它也将不起作用,因为jest.mock需要字符串,模块的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 个答案:

答案 0 :(得分:1)

不确定这是否有帮助,但可能会给您带来想法。

首先,上面的示例:

// 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() {...}
}

这使您可以在Component 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'); }

component.js可以:

import { parentFunction } from './utils';

您可以在测试中做到:

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

如您所见,还有许多可行的方法,尽管我不确定测试的价值,但您应该测试组件的输出/功能,而不是调用它,而是在{{1 }}是给定的,只有在有人转换为函数或更改了生命周期名称的情况下,它才会中断。

答案 1 :(得分:1)

如果未将函数作为对象方法调用,则无法监视函数调用。

this answer中所述,由于ES模块的工作方式,只有从某个模块导出并在另一个模块中使用该功能时,才可能监视或模拟该功能。这样,就可以在模块*对象上对其进行侦听,或与jest.mock进行模拟。

如果不是这种情况,则应进行间接测试:

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