【发布时间】:2020-01-02 21:07:24
【问题描述】:
我无法模拟第三方依赖项。我总是收到这个错误:
无法窥探未定义的属性,因为它不是函数; 取而代之的是未定义
以下是此问题的详细信息。首先,这是我正在测试的功能:
文件:src/js/mp_wrapper.js
import { Viewer } from 'third-party';
module.exports = {
createViewer: container => {
if (util.isElement(container)) {
return new Viewer(container);
} else {
throw new Error(
'Invalid Element when attempting to create underlying viewer.',
);
}
},
}
查看我第三方的源码,Viewer 很简单,长这样:
function Viewer(){
// Doing things
}
Viewer.prototype.foo = function(){
}
module.exports = Viewer;
最后,这是我的测试。
文件:/tests/mp_wrapper.spec.js
import { Viewer } from 'third-party`;
import mp_wrapper from '../src/js/mp_wrapper';
describe('mp_wrapper', () => {
describe('createViewer', () => {
test('returns a new instance of the Viewer class', () => {
const spy = jest.spyOn(Viewer).mockImplementation(() => jest.fn());
// It fails on the line above... -> "Cannot spy the undefined property because it is not a function; undefined given instead"
const testElement = document.createElement(testElement);
let viewer = mp_wrapper.createViewer(testElement);
expect(spy).toHaveBeenCalled();
expect(viewer).toBeInstancecOf(Viewer);
spy.mockRestore();
});
});
});
如何模拟和监视查看器本身?
我过去做过:
const spy = jest.spyOn(Viewer.prototype, 'foo').mockImplementation(() => jest.fn());
我也尝试过default,但没有成功:
const spy = jest.spyOn(Viewer, 'default').mockImplementation(() => jest.fn());
但现在我想监视 Viewer。
编辑:
这是我的最终解决方案。 @brian-lives-outdoors 答案是正确的,但我没有准确描述我的问题。我试图模拟的第三方库稍微复杂一些,因为它导出了一个包含多个构造函数的模块。它看起来像这样:
module.exports = {
Viewer: require('./path/Viewer'),
Foo: require('./foo_path/Foo'),
Bar: require('./bar_path/Bar')
}
然后./path/Viewer 内部就像我之前描述的那样。
这就是我的解决方案最终的样子:
import { Viewer } from 'lib';
import mp_wrapper from '../src/js/mp_wrapper';
jest.genMockFromModule('lib');
jest.mock('lib');
describe('mp_wrapper', () => {
describe('createViewer', () => {
test('returns a new instance of the Viewer class and sets the local _viewer property', () => {
const testContainer = document.createElement('div');
const viewer = mp_wrapper.createViewer(testContainer);
expect(Viewer).toHaveBeenCalledWith(testContainer); // Success!
expect(viewer).toBeInstanceOf(Viewer); // Success!
});
});
});
@brian-lives-outdoors 我不明白的是,如果我注释掉上面的jest.mock('lib'); 行,它就不起作用了……为什么?
为什么genMockFromModule 本身不够用?
【问题讨论】:
-
@brian-lives-outdoors 对这个问题有什么想法吗?您似乎是模拟依赖项方面的专家
标签: javascript unit-testing jestjs