有没有办法用Jest模拟私有函数?

时间:2017-04-06 21:18:45

标签: javascript unit-testing jestjs es6-modules

我要测试的ES6模块如下所示:

function privateFunction() {
   ...
}
export function publicFunction() {
   ... does something ...
   privateFunction()
   ... does something else ...
}

我正在使用JEST进行单元测试,我试图找到一种方法来测试publicFunction并通过模拟它来避免执行privateFunction,但我无法在模拟尝试中成功。有什么想法吗?

4 个答案:

答案 0 :(得分:13)

我找到了一种使用 babel-plugin-rewire 模块来模拟我的私人功能的方法。

package.json 中,我有以下内容:

  "devDependencies": {
    ...
    "babel-plugin-rewire": "1.0.0-beta-5",
    "babel-jest": "18.0.0",
    ...

.babel.rc 中,我有以下内容:

{
  "presets": [
    "es2015",
    "stage-0",
    "react"
  ],
  "env": {
    "test": {
      "plugins": [
        "babel-plugin-rewire"
      ]
    }
  },
  ...

此时我能够模拟私有函数:

import * as moduleToTest from './moduleToTest.js'

describe('#publicFunction', () => {
  it('mocks private function', () => {
    moduleToTest.__Rewire__('privateFunction', () => { console.log('I am the mocked private function') })
    ...
  })
})

答案 1 :(得分:5)

没有办法解决JavaScript的本质问题。该函数绑定到模块的范围,因此无法知道此函数是否存在于外部,因此无法访问该函数,最终无法模拟它。

也许更重要的是,您不应该测试被测对象的内部,而只测试公共API。因为这是重要的一切。只要公共API保持稳定,就没有人关心内部的内容。

答案 2 :(得分:1)

如果要模拟私有功能,请尝试使用 prototype 。 例如,您需要模拟下一个类的 privateFunction

xcode-select -p

因此,您应该在 jest.spyOn 函数中使用 Module.prototype

export class Module {
    public publicFunction() {
        // do something
        this.privateFunction();
        // do something
    }

    private privateFunction() {
        // do something
    }
}  

答案 3 :(得分:0)

没有什么可以阻止您嘲笑私有函数。不要忘记,作为模拟插入的任何内容都将替换为模块;如果您无法访问要测试的功能,请自己添加该功能。

假设您有一些要测试的课程。

export class MyModule {
  public myPublicFunc() {
    return this.myPrivateFunc();
  }

  private myPrivateFunc() {
    return 5;
  }
}

您可以像这样测试。

import { MyModule } from './whatever'

describe('MyModule public function', () => {
  it('should call a private function', () => {
    // Arrange
    const mod = new MyModule();
    mod.myPrivateFunc = jest.fn();

    // Act
    mod.myPublicFunc();

    // Assert
    expect(mod.myPrivateFunc).toHaveBeenCalled();
  });
});

如果您做的和我完全一样,Typescript会抱怨,但是您可以通过类型转换来解决。