如何清除 Jest 模拟实现以进行下一次测试?
Posted
技术标签:
【中文标题】如何清除 Jest 模拟实现以进行下一次测试?【英文标题】:How to clear Jest mock implementation for next tests? 【发布时间】:2019-12-20 18:37:50 【问题描述】:我正在设置 Jest 来测试一个打字稿应用程序。
如何清除模拟函数并恢复其他测试的原始实现?
模拟我使用过的函数:jest.fn().mockImplementationOnce()
到目前为止,我已经在 beforeEach 和 afterEach 中尝试了 jest.clearAll() / resetModules() / resetAllMocks() ,但没有任何成功。
app.test.ts
import App from './app';
import DbService from './lib/dbService';
describe('App', () =>
let dbService: DbService;
let app: App;
beforeEach(() =>
jest.clearAllMocks();
dbService = new DbService();
app = new App();
);
describe('getUsers', () =>
it('Should get an array users #1', () =>
expect(app).toBeInstanceOf(App);
const allUsers = app.getAllUsers();
expect(allUsers[0].id).toBeDefined();
);
it('should return an error #2', () =>
DbService.prototype.getAllUsers =
jest.fn().mockImplementationOnce(() =>
return new Error('No connection to DB');
);
expect(app.getAllUsers()).toEqual(new Error('No connection to DB'));
);
it('Should get an array users #3', () =>
expect(app).toBeInstanceOf(App);
const allUsers = app.getAllUsers();
expect(allUsers[0].id).toBeDefined();
);
);
);
app.ts
import DbService from './lib/dbService';
export default class App
private dbService: DbService;
constructor()
this.dbService = new DbService();
getAllUsers()
return this.dbService.getAllUsers();
lib/dbService.ts
let instance: DbService;
export class DbService
constructor()
if (!instance)
instance = this;
return instance;
getAllUsers()
return [
id: 1, username: 'john',
id: 2, username: 'bill'
]
我希望测试 #3 像测试 #1 一样通过,但它实际上失败并出现以下错误:
FAIL src/app.test.ts
App
getUsers
√ Should get an array users #1 (3ms)
√ should return an error #2 (1ms)
× Should get an array users #3 (1ms)
● App › getUsers › Should get an array users #3
TypeError: Cannot read property '0' of undefined
31 | expect(app).toBeInstanceOf(App);
32 | const allUsers = app.getAllUsers();
> 33 | expect(allUsers[0].id).toBeDefined();
| ^
34 | );
35 | );
36 | );
【问题讨论】:
【参考方案1】:我不确定这是否是jest
实现此目的的方式,但我认为您可以将原始方法实现保存在一个变量中,并在每次测试后重新设置该方法,以防它在测试中被模拟。
例如
describe('App', () =>
let dbService: DbService;
let app: App;
let originalGetAllUsersFn = DbService.prototype.getAllUsers;
//...
afterEach(() =>
// restore mocked method
DbService.prototype.getAllUsers = originalGetAllUsersFn;
);
);
【讨论】:
【参考方案2】:Jest 具有设置/拆卸功能:
https://flaviocopes.com/jest/#setup 要在所有测试运行之前执行一次操作,请使用 beforeAll() 函数:
beforeAll(() =>
//do something
)
要在每次测试运行之前执行某些操作,请使用 beforeEach():
beforeEach(() =>
//do something
)
拆解 就像你可以使用 setup 一样,你也可以在每次测试运行后执行一些操作:
afterEach(() =>
//do something
)
在所有测试结束后:
afterAll(() =>
//do something
)
在设置函数中进行模拟并在拆卸中恢复
【讨论】:
但是如何使用 setup 和 restore 进行单次测试? 如果您只想在特定情况下模拟,那么不幸的是,您还需要在该测试中恢复。它可能又长又慢,但您可以分别模拟所有人并在每次测试之前/之后恢复所有内容(即 beforeEach() 中的所有模拟)这不是最好的解决方案,但这是我过去必须做的事情以上是关于如何清除 Jest 模拟实现以进行下一次测试?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jest.mock 模拟 useRef 和反应测试库
使用 MSW 和 Jest 时如何在请求之间的测试中清除 RTK 查询缓存?