如何处理模块和打字稿类型的笑话模拟功能
Posted
技术标签:
【中文标题】如何处理模块和打字稿类型的笑话模拟功能【英文标题】:how to deal with jest mock function of a module and typescript type 【发布时间】:2017-12-10 00:51:23 【问题描述】:我使用ts-jest
和jest
用打字稿编写我的测试文件。
我很困惑如何输入模块的模拟函数。
这是我的代码:
./module.ts
:
import IObj from '../interfaces';
const obj: IObj =
getMessage()
return `Her name is $this.genName(), age is $this.getAge()`;
,
genName()
return 'novaline';
,
getAge()
return 26;
;
export default obj;
./module.test.ts
:
import * as m from './module';
describe('mock function test suites', () =>
it('t-1', () =>
// I think the jest.Mock<string> type here is not correct.
m.genName: jest.Mock<string> = jest.fn(() => 'emilie');
expect(jest.isMockFunction(m.genName)).toBeTruthy();
expect(m.genName()).toBe('emilie');
expect(m.getMessage()).toEqual('Her name is emilie, age is 26');
expect(m.genName).toHaveBeenCalled();
);
);
如何输入模块m
的模拟函数genName
?
typescript
在这里给我一个错误:
错误:(8, 7) TS2540: 无法分配给“genName”,因为它是常量或只读属性。
【问题讨论】:
【参考方案1】:您想模拟模块,然后更改其中的导出函数。这应该替换您的导入语句。
jest.mock('./module', () => (
genName: jest.fn().mockImplementation(() => 'emilie')
))
【讨论】:
这不起作用,因为 genName 的范围仅限于该块,并且在整个文件中不可用 我在整个代码中都在使用它,所以它确实有效。如果您需要测试是否调用了 genName(或类似的东西),您可以将 jest.fn() 分配给块外部的 mock* 变量并引用它:genName: mockGenName
然后 expect(mockGenName).toHaveBeenCalled()
或其他。跨度>
@trevorgk 建议的解决方案工作正常。我只想强调您可能想要更改特定测试的实现:it('returns franc', () => m.genName.mockImplementationOnce(() => 'franc') )
@phillyslick 感谢您的解决方案,但在这种情况下,您如何测试功能本身?喜欢:expect(genName()).toReturnSomething...
?【参考方案2】:
import * as m from './module'
jest.mock('./module', () => (
genName: jest.fn().mockImplementation(() => 'emilie')
// will return "enilie" for all tests
))
it('returns franc', () =>
m.genName.mockImplementationOnce(() => 'franc')
// will return "franc" for this particular test
)
【讨论】:
第二个 mockImple 不起作用我得到 Property 'mockImplementation' does not exist on type '() => Promise'。【参考方案3】:我在嘲笑它:
jest.mock('./module')
const genName = require('./module')
在我的测试中:
genName.mockImplementationOnce(() => 'franc')
非常适合我,没有打字错误
【讨论】:
如果能解释你的答案就太好了【参考方案4】:这就是我解决相同问题的方法,也是我现在进行所有嘲笑和监视的方法。
import * as m from './module';
describe('your test', () =>
let mockGenName;
beforeEach(() =>
mockGenName = jest.spyOn(m,
'genName').mockImplemetation(() => 'franc');
)
afterEach(() =>
mockGenName.mockRestore();
)
test('your test description', () =>
// do something that calls the genName function
expect(mockGenName).toHaveBeenCalledTimes(1);
)
)
使用此设置,您可以以编程方式更改不同测试的模拟实现,然后断言该函数已被调用以及它被调用的内容,同时在测试之间和所有测试之后清除模拟。
【讨论】:
我得到 TypeError: jest.spyOn(...).mockImplemetation is not a function @ykonda 我修正了拼写错误【参考方案5】:我得到错误的原因是:
模块对象 foo 的属性(import * as foo from 'foo')类似于冻结对象的属性。
欲了解更多信息,请参阅In ES6, imports are live read-only views on exported values
当我将import * as m from './module'
更改为import m from './module';
时,错误消失了。
软件包版本:
"typescript": "^3.6.4"
"ts-jest": "^24.1.0"
"jest": "^24.9.0",
jest.config.js
:
module.exports =
preset: 'ts-jest/presets/js-with-ts',
//...
tsconfig.json
:
"compilerOptions":
"target": "es6",
"module": "commonjs",
//...
【讨论】:
【参考方案6】:试试这个 - https://jestjs.io/docs/mock-function-api#typescript
简而言之,只有三种可能的策略
-
模拟要导入的整个模块并获取模拟函数的处理程序以对其进行操作(jest.Mock()、jest.MockedFunction)
模拟部分导入的模块并获取模拟函数的处理程序以对其进行操作(jest.Mock() with factory, jest.MockedFunction)
按原样导入模块,然后监视需要模拟的函数 (jest.spy())
【讨论】:
以上是关于如何处理模块和打字稿类型的笑话模拟功能的主要内容,如果未能解决你的问题,请参考以下文章