我有一个这样定义的打字稿文件:
// myType.tsx
import { Foo } from 'foo';
[...]
export interface MyType extends IDisposable {
[...]
}
export abstract class MyTypeBase implements MyType {
innerFoo: Foo | null | undefined;
get foo(): Foo {
return this.innerFoo;
}
[...]
}
我正在尝试测试另一个依赖于这个 MyType
的类,我想模拟 foo()
getter。
在我的测试文件中,一旦我将以下内容添加到文件中:
[...]
import { MyType } from 'path/to/MyType';
[...]
jest.mock('path/to/MyType', () => {
return jest.fn().mockImplementation(() => {
return {foo: () => mockFoo}; //mockFoo is defined earlier in the file.
})
});
运行测试时出现错误:
Class extends value undefined is not a constructor or null
这仅在我包含 jest.mock(...)
行时发生。
从其他相关问题来看,我认为这可能是由循环依赖引起的,但我没有看到如何通过调用 jest.mock
来引入这种情况?我可以看到,当我注释掉这段代码时,其他被击中的断点没有被击中,所以看起来好像添加这个模拟会导致我的测试因为这个原因过早失败。
有人遇到过这种情况吗?
答案 0 :(得分:0)
问题在the documentation中有解释:
<块引用>工厂参数的一个限制是,由于对 jest.mock() 的调用被提升到文件的顶部,所以不可能先定义一个变量然后在工厂中使用它。以单词“mock”开头的变量是一个例外。由您来保证它们会按时初始化!例如,由于在变量声明中使用了 'fake' 而不是 'mock',以下将抛出一个范围外错误
使用 mockFoo
变量名允许在 jest.mock
工厂函数中使用它,风险自负。
mockFoo 在文件的前面定义
这不是真的,因为 jest.mock
被提升到各自的导入之上,但它引用的变量在模拟模块被评估时没有定义。对于急切评估的模拟模块,需要在工厂内定义模拟。如果需要在测试中访问,可以通过模块公开。
foo
是属性访问器,但被模拟为函数。
还有一个模拟模块是 CommonJS,这将阻止命名导入在大多数设置中被正确映射,模拟模块中应该有 __esModule: true
。