【问题标题】:extracting mocked function for easier mocking of function behavior with jest提取模拟函数,以便更轻松地用玩笑模拟函数行为
【发布时间】:2021-12-01 19:32:26
【问题描述】:

我正在使用 jest 和 nodejs 并为我的模型进行续集。对于我的测试,我想模拟findAll 的返回值以覆盖测试场景。抱歉,如果这是一个非常新手的问题,但我在这个问题上处于死胡同。

init-models.js

module.exports = function initModels(sequelize) {
  //model relationship code here
  ...
  ...
  //end of model relationship code

  return {
    records,
    anotherModel,
    alsoAnotherModel
  };
};

repository.js

const sequelize = require('../sequelize');
const initModels = require('../model/init-models');

let {
  records,
  anotherModel,
  alsoAnotherModel
} = initModels(sequelize);

const fetchRecords = async () => {
  console.info('Fetching records...');
  return await records.findAll({sequelize parameters here});
}

repository.test.js 这可以工作,但需要灵活地模拟findAll() 返回值/或抛出错误

const repository = require('../../../src/db/repository/repository');
const initModels = require('../../../src/db/model/init-models');

jest.mock('../../../src/db/model/init-models', () => {
    return function() { 
        return {
            records: {
                findAll: jest.fn().mockImplementation(() => [1,2,3])
            }
            //the rest of the code for other models
        }
    }
});

describe('fetchRecords', () => {
    beforeEach(()=> {
    });

    test('should return correct number of records', async () => {
        const result = await repository.fetchRecords();
        expect(result.size).toStrictEqual(3);        //test passed
    });
})

为了允许模拟 findAll 的结果,我尝试将其提取出来,以便可以更改每个测试场景的结果,但它不起作用。我错过了什么?

const mockRecordsFindAll = jest.fn();

jest.mock('../../../src/db/model/init-models', () => {
    return function() { 
        return {
            records: {
                findAll: () => mockRecordsFindAll
            }
            //the rest of the code for other models
        }
    }
});

describe('fetchRecords', () => {
    beforeEach(()=> {
        mockRecordsFindAll.mockReset()
    });

    test('should return correct number of records', async () => {
        mockRecordsFindAll.mockImplementation(() => [1,2,3]); //should expect length 3
        const result = await repository.fetchRecords();
        expect(result.size).toStrictEqual(3);            //fails, findAll was not mocked
    });
})

【问题讨论】:

  • 尝试使用mockRecordsFindAll 作为findAll 的值。 findAll: () => mockRecordsFindAll -> findAll: mockRecordsFindAll.
  • 我会收到ReferenceError: Cannot access 'mockRecordsFindAll' before initialization。我认为这是因为 jest 会将 jest.mock(....) 提升到顶部,然后在执行 mockRecordsFindAll 的初始化之前。
  • 知道了,您可以使用decorator pattern。它应该有助于提升机。 findAll: function () { return mockRecordsFindAll.call(this, arguments); }
  • findAll: function () { return mockRecordsFindAll.call(this, arguments); } 有效!您可以将您的评论作为答案,将接受它。谢谢你:)

标签: node.js unit-testing jestjs sequelize.js


【解决方案1】:

问题是 mockRecordsFindAll 被返回而不是被执行。 由于 @Gid 加工只是返回 mockRecordsFindAll 会导致初始化问题(由于提升)。

这种情况的解决方案是使用decorator pattern 来允许mockRecordsFindAll 之后被初始化。

const mockRecordsFindAll = jest.fn();

jest.mock('../../../src/db/model/init-models', () => {
    return function() { 
        return {
            records: {
                findAll: function () { 
                   return mockRecordsFindAll.call(this, arguments); 
                }
            }
        }
    }
});

describe('fetchRecords', () => {
    ...
})

【讨论】:

    猜你喜欢
    • 2021-02-07
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多