javascript - 如何清除 Jest 模拟实现以进行下一步测试?

标签 javascript typescript unit-testing jestjs

我正在设置 Jest 来测试 typescript 应用程序。

如何清除模拟函数并恢复其他测试的原始实现?

模拟我使用过的函数: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 | });

最佳答案

我不确定这是否是实现此目的的jest方法,但我认为您可以将原始方法实现保存在变量中,并在每次测试后重新设置该方法,以防万一在测试中被 mock 。

例如

describe('App', () => {    
  let dbService: DbService;
  let app: App;
  let originalGetAllUsersFn = DbService.prototype.getAllUsers;

  //...

  afterEach(() => {
    // restore mocked method
    DbService.prototype.getAllUsers = originalGetAllUsersFn;
  });

});

关于javascript - 如何清除 Jest 模拟实现以进行下一步测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57490718/

相关文章:

angular - 如何发出带有值的对象

javascript - Angular http post 通过服务将数据返回给组件

typescript - NestJS 在 e2e 测试中模拟 JWT 身份验证

ios - 什么时候使用 specta 的 'sharedExamplesFor' ?

c++ - 当前正在运行哪个单元测试?

Javascript子类对象不保留基类的属性/方法

javascript - 如何简化多个嵌套 if else 语句的代码

node.js - 调试在 Visual Studio Code 1.19.3 中不起作用

javascript - 在警报弹出之前设置自定义输入的值

javascript - 如何使用 Raphael 和 jQuery 检测 IE 上的点击或鼠标按下