Jestjs如何测试在另一个函数内部调用的函数

28

我使用jest和react-test-renderer进行测试。测试应该很简单,但是我很难找到合适的示例。我尝试过类似这样的方式(一般将函数保留在单独的文件中):

utils.js

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

实用工具测试.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,而不是函数本身。

上面的例子不起作用,我正在寻找替代方案。但是,在使用ShallowRenderer呈现组件后,这个方法可以工作。我想实现一个类似的行为,其中一个函数嵌套在另一个函数中。

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个回答

10

不确定这是否有帮助,但它可能会给你一些想法。

首先,看看上面的例子:

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

这可以让您创建一个漏洞并监视组件原型。

例如:

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();

你可以看到,有很多可能的方法,尽管我不确定那个测试的价值,你应该测试组件的输出/功能而不是它所调用的内容,在componentDidMount上运行某些东西是必然的,并且只有在有人将其转换为函数或更改生命周期名称时才会出现问题。


感谢回复。然而,这里不是检查是否调用了parentFunction的问题,而是检查是否调用了parentFunction内部的childFunction。我确实导出了我的子函数,只是为了测试。我将编辑我的问题以展示我的文件结构是什么样子的。 - Dune

10
如果函数不是作为对象方法被调用,就没有办法监听函数调用。正如这个回答所解释的那样,由于 ES 模块的工作方式,只有在模块中导出并在另一个模块中使用的函数才能被监听或模拟。这样可以监听模块* 对象上的函数或者通过 jest.mock 进行模拟。
如果不是这种情况,则应间接进行测试:
expect(childFunction()).toBe('something');
expect(parentFunction()).toBe('something');

是的,看来我可以忘记观察是否在组件之外的某个地方调用了函数。知道我想做不可能的事情是很有价值的。 :) - Dune

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接