开玩笑-使用spyOn函数时,请确保未将间谍对象称为

时间:2019-04-25 15:21:52

标签: javascript angular jestjs

从Jest注释中:注意:默认情况下,jest.spyOn还调用间谍方法。

在我的Angular组件中。

ngAfterViewInit(): void {
  this.offsetPopoverPosition();
}

在我的规范中:

it('ngAfterViewInit() method should call offsetPopoverPosition() method', () => {
    const mockListener = jest.spyOn(cmp, 'offsetPopoverPosition');
    const spy = mockListener.mockImplementation(() => {
      console.log('in the mock');
    });

    cmp.ngAfterViewInit();
    expect(spy).toHaveBeenCalled();
  });

简单。然而,原始功能仍在被调用。 我检查了Jest 23.x文档: https://jestjs.io/docs/en/23.x/jest-object#jestspyonobject-methodname https://jestjs.io/docs/en/23.x/mock-function-api#mockfnmockimplementationfn

互联网上的例子很少,但我无法阻止玩笑者调用原始的offsetPopoverPosition()方法。

有什么想法吗?

我正在交叉链接到Jest github问题,由于某种原因该问题已关闭,但未解决。

Jest spyOn() calls the actual function instead of the mocked

2 个答案:

答案 0 :(得分:1)

根据我的经验,问题在于您正在重置原始模拟的意图。创建间谍程序时,它具有自己的实现,通过使用模拟实现来覆盖它,我已经体验到了您所描述的场景-相反,请尝试以下操作:

cmp.offsetPopoverPosition = jest.fn().mockImplementation(() => {
      console.log('in the mock');
    });
const mockListener = jest.spyOn(cmp, 'offsetPopoverPosition');
// ... do work
expect(mockListener).toHaveBeenCalled[Times,With]()

这还假设cmp是组件的一个实例,而不仅仅是它的定义引用

编辑:请注意,在要测试的组件内部模拟消息化功能是对单元测试的错误指导。而不是测试与sameComponent.method的通信-测试链接方法使用的所有消息使用在要测试的组件之外-对于简短的问题内容,​​请忽略我给出的测试方法建议它的阅读茶叶与您的单元测试设计无关

答案 1 :(得分:0)

我相信我在这里遇到同样的问题,所以也许我们会互相帮助。 我有3个文件

  • 一个名为 dbManager.js
  • 另一个名为 mssqlPool.js
  • 然后是测试文件 dbManager.test.js

测试的文件位于 ./ src / db文件夹中。

测试文件位于 ./ test / db文件夹中(基本上复制了src文件夹树)。

我想模拟 mssqlPool.js

module.exports = {
  mssqlPool: async config => {
    // actual connection with an await (in case it matters)
  }
}

这里的DBManger是带有构造函数的类:

const { mssqlPool } = require('./mssqlPool');

module.exports = class DBManager {
  constructor(config) {}
}

async initPool() {
    if (global.DB_TYPE === 'mssql') {
      this.pool = await mssqlPool(this.config);
      return true;
    }}

const mssqlPool = require('../../../src/helpers/db/mssqlPool');
const DbManager = require('../../../src/helpers/db/dbManager');

let dbManager;

beforeEach(() => {
  const mockedConfig = {
    type: '<type: mssql/postgresql>',
    user: '<user>',
    password: '<mdp>',
    server: '<host>',
    database: '<db_name>',
    pool: {
      max: 10,
      min: 0,
      idleTimeoutMillis: 30000
    }
  };
  dbManager = new DbManager(mockedConfig);

  jest.spyOn(mssqlPool, 'mssqlPool').mockImplementation(() => Promise.resolve());
});

afterEach(() => {
  jest.restoreAllMocks();
});

describe('DbManager', () => {
  test('initPool', async () => {
    global.DB_TYPE = 'mssql';
    await dbManager.initPool();

    expect(mssqlPool.mssqlPool).toHaveBeenCalled();
  });});

这是行不通的,测试失败了,因为它会尝试使用mssqlPool函数并使用我的mockedConfig连接到数据库,而我显式地使用

  jest.spyOn(mssqlPool, 'mssqlPool').mockImplementation(() => Promise.resolve());

我已经将mssqlPool文件从module.exports=config=>{}更改为module.exports={mssqlPool:config=>{}},以便能够使用spyOn