如何模拟内部函数?

时间:2019-08-22 15:55:29

标签: javascript node.js unit-testing mocking jestjs

当前,我正在向测试控制器编写代码,该代码需要调用模型。为了避免测试的副作用,我需要模拟模型。但是,由于模型使用内部函数作为构造函数,因此以非常复杂的方式编写。我尝试了不同的方法,但仍然无法达到目的。

models / mondayModel.js

var mondayModel = function() {
  function fnA (req, callback) { 
   ...


  }
  function fnB (req, callback) { }
  function fnC (req, callback) { }
  function fnD (req, callback) { }
  return {
    fnA: fnA,
    fnB: fnB,
    fnC: fnC,
    fnD: fnD
  }
}

module.exports = mondayModel

controller / boxController.js

var MondayModel = require('../models/mondayModel');


function transfer(req, res, next) {
   ...
   var mondayModel = new MondayModel();
   mondayModel.fnA(req, payload, function(error, result) {
   ...
   }
}

boxController-test.jest


let boxController = null

describe('money tracker', () => {
    beforeAll(() => {        
        jest.mock('../../../../models/mondayBox',
            () => ({
              mondayBox: {
                fnA: jest.fn(),
                fnB: jest.fn(),
                fnC: jest.fn(),
                fnD: jest.fn()
            }
        }))    
    )
        boxController = require('../controllers/boxController')
    })

    test('success case', done => {
       const req = {}
       const payload = {}
       boxController.transfer(req, payload, (cbErr, cbRes) => {expect(cbRes).toBe('OK')
    }
}

但是它给了TypeError: mondayModel is not a constructor

我可以知道如何解决这个模拟(内部)函数吗? 谢谢

3 个答案:

答案 0 :(得分:1)

请注意,the arrow function不能作为构造函数调用。以下代码段将说明您的情况。

var mondayModel = function () {
}

var mondayModelArrow = () => {} 
try {
  new mondayModel() // sucessfully
  new mondayModelArrow() // will throw exception
}
catch(e){
  console.error(e.stack)
}

答案 1 :(得分:1)

错误说明了一切。它不是构造函数。只需放下new

var mondayModel = MondayModel();

或者如果您坚持要使其成为构造函数,则可以像这样更改MondayModel并继续使用new

var mondayModel = function() {
  this.fnA = function (req, callback) { ... }
  this.fnB = function (req, callback) { ... }
  this.fnC = function (req, callback) { ... }
  this.fnD = function (req, callback) { ... }
}

答案 2 :(得分:1)

首先,我认为jest.mock应该放在顶部。它会被吊到顶部,但是我不知道如果放在另一个函数中会发生什么。

而且,您应该传递一个函数,该函数返回一个可更新的

const model = require('../mondayModel');

jest.mock('../../../../models/mondayBox', () => function Model() {
  return {
    fnA: jest.fn(),
    fnB: jest.fn(),
    fnC: jest.fn(),
    fnD: jest.fn(),
  }
});

在您的情况下,

const MondayModel = require('../mondayModel');
var mondayModel = new MondayModel();

本质上是

const MondayModel = {
  mondayBox: {
    fnA: jest.fn(),
    fnB: jest.fn(),
    fnC: jest.fn(),
    fnD: jest.fn()
  },
};
var mondayModel = new MondayModel();

您可以尝试对其进行控制台记录