如何在 Jest 中模拟此方法链?

Posted

技术标签:

【中文标题】如何在 Jest 中模拟此方法链?【英文标题】:How do I mock this method chain in Jest? 【发布时间】:2019-01-26 02:52:52 【问题描述】:
zoomOut(callback) 
        // Zooms out the current screen
        this.view.current.zoomOut(300).done(() => 
            (hasCallback(callback)) && callback();
        );
    

我正在尝试测试上面的功能,但我不断收到以下错误:

TypeError: this.view.current.zoomOut(...).done 不是函数

如何在 Jest 中模拟这个方法链?

【问题讨论】:

这不是方法链,它只是调用深度嵌套对象上的方法。 【参考方案1】:

你可以试试这个:

const mockZoomOut = jest.fn(() => ( done(cb)  cb();  ));
const mockThis = 
    view: 
        current: 
            zoomOut: mockZoomOut,
        ,
    ,
;

test('it does', () => 
    const cb = jest.fn();
    zoomOut.apply(mockThis, [cb]);
    expect(mockZoomOut).toHaveBeenCalledTimes(1);
    expect(cb).toHaveBeenCalledTimes(1);
);

参见Jest Mock Functions 和fn.apply。

如果您要测试整个类的行为,那么您可以将要测试的实例设置为 this.view.current.zoomOut 以某种方式变为 mockZoomOut

【讨论】:

对于任何有兴趣的人来说,实现this.view.current.zoomOut 成为mockZoomOut 的一种方法是依赖注入。【参考方案2】:

感谢 BudgieInWA,我能够通过返回 done 来解决这个问题。

对于那些使用 Enzyme 测试 React 组件的人,您可以这样做:

it('should call callback', () => 
    const wrapper = shallow(<Zoom ...minProps/>);
    const instance = wrapper.instance();

    const callback = jest.fn();

    instance.view = 
        current: 
            zoomOut: jest.fn(() => 
                return 
                    done: jest.fn((callback) => 
                        callback();
                    )
                ;
            )
        
    ;

    expect(callback).toHaveBeenCalledTimes(0);
    instance.zoomOut(callback);
    expect(callback).toHaveBeenCalledTimes(1);
);

【讨论】:

以上是关于如何在 Jest 中模拟此方法链?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React Jest 测试中“模拟”navigator.geolocation

如何在 Jest 单元测试中模拟在 `created` Vue 生命周期挂钩中调用的方法,而不使用`shallowMount` 中已弃用的`methods` 参数? [复制]

如何使用 jest.fn() 在 jest 中使用 typescript 模拟函数

如何在带有 Jest 的 react-native 中使用模拟的 fetch() 对 API 调用进行单元测试

如何在 Jest 中模拟一个函数

如何在 javascript 中模拟内部 JSON 对象?