如何访问和测试node.js模块中的内部(非导出)功能?

我试图弄清楚如何在nodejs(最好是用mocha或jasmine)中测试内部(即不导出)功能。而且我不知道!

假设我有一个像这样的模块:

function exported(i) {
   return notExported(i) + 1;
}

function notExported(i) {
   return i*2;
}

exports.exported = exported;

和以下测试(摩卡):

var assert = require('assert'),
    test = require('../modules/core/test');

describe('test', function(){

  describe('#exported(i)', function(){
    it('should return (i*2)+1 for any given i', function(){
      assert.equal(3, test.exported(1));
      assert.equal(5, test.exported(2));
    });
  });
});

有什么办法可以对notExported功能进行单元测试而不实际导出功能,因为它不是要公开的?

蛋蛋Pro樱2020/03/24 17:06:37

诀窍是将NODE_ENV环境变量设置为类似变量test,然后有条件地将其导出。

假设尚未全局安装Mocha,则可以在应用目录的根目录中包含一个Makefile,其中包含以下内容:

REPORTER = dot

test:
    @NODE_ENV=test ./node_modules/.bin/mocha \
        --recursive --reporter $(REPORTER) --ui bbd

.PHONY: test

该make文件在运行mocha之前会设置NODE_ENV。然后,您可以make test在命令行中运行Mocha测试

现在,您可以有条件地导出通常仅在运行mocha测试时才导出的函数:

function exported(i) {
   return notExported(i) + 1;
}

function notExported(i) {
   return i*2;
}

if (process.env.NODE_ENV === "test") {
   exports.notExported = notExported;
}
exports.exported = exported;

另一个答案建议使用vm模块评估文件,但这不起作用,并抛出错误,指出未定义导出。

路易Sam2020/03/24 17:06:37

我发现了一种非常简单的方法,可以让您从测试中测试,监视和模拟这些内部函数:

假设我们有一个像这样的节点模块:

mymodule.js:
------------
"use strict";

function myInternalFn() {

}

function myExportableFn() {
    myInternalFn();   
}

exports.myExportableFn = myExportableFn;

如果现在我们想在不将其导出到生产环境中的同时进行测试监视以及模拟,myInternalFn 必须像这样改进文件:

my_modified_module.js:
----------------------
"use strict";

var testable;                          // <-- this is new

function myInternalFn() {

}

function myExportableFn() {
    testable.myInternalFn();           // <-- this has changed
}

exports.myExportableFn = myExportableFn;

                                       // the following part is new
if( typeof jasmine !== "undefined" ) {
    testable = exports;
} else {
    testable = {};
}

testable.myInternalFn = myInternalFn;

现在,您可以myInternalFn在使用它的任何地方进行测试,监视和模拟testable.myInternalFn并且在生产中不会将其导出

番长猴子2020/03/24 17:06:36

您可以使用vm模块创建一个新上下文并评估其中的js文件,就像repl一样。那么您就可以访问它声明的所有内容。