【问题标题】:Jestjs how to test function being called inside another functionJestjs如何测试在另一个函数中调用的函数
【发布时间】:2019-03-10 01:28:00
【问题描述】:

对于测试,我使用 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,而不是函数本身。

上面的例子不起作用,我正在寻找替代方法。但是,这在使用 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();
  });
});

【问题讨论】:

    标签: javascript reactjs jestjs react-test-renderer


    【解决方案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() {...}
    }
    

    这使您可以在组件原型上创建穿刺和窥探。

    例如

    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。而且我确实导出了我的子函数,只是为了测试。我将编辑我的问题以显示我的文件结构。
    【解决方案2】:

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

    正如this answer 中所解释的,由于 ES 模块的工作方式,只有从模块中导出并在另一个模块中使用的函数才能窥探或模拟函数。这样它就可以在模块 * 对象上被监视,或者被 jest.mock 模拟。

    如果不是这样,应该间接测试:

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

    【讨论】:

    • 是的,我似乎忘记了观察某个函数是否在某个不是组件的地方被调用。知道我想做不可能的事情是很有价值的。 :)
    猜你喜欢
    • 2014-05-08
    • 2020-05-13
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 2018-06-12
    相关资源
    最近更新 更多