我试图弄清楚如何在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函数进行单元测试,而不实际导出它,因为它不打算公开?


当前回答

我一直在使用一种不同的方法,没有任何依赖: 有一个包含我想测试的所有本地函数的__testing导出,该值取决于NODE_ENV,因此它只在测试中可访问:

// file.ts
const localFunction = () => console.log('do something');
const localFunciton2 = () => console.log('do something else');
export const exportedFunction = () => {
    localFunction();
    localFunciton2();
}
export const __testing = (process.env.NODE_ENV === 'test') ? {
    localFunction, localFunction2
} : void 0;

// file.test.ts
import { __testing, exportedFunction } from './file,ts'
const { localFunction, localFunction2 } = __testing!;
// Now you can test local functions

其他回答

重新布线模块绝对是答案。

下面是我使用Mocha访问未导出函数并测试它的代码。

application.js:

function logMongoError(){
  console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
}

. js:

var rewire = require('rewire');
var chai = require('chai');
var should = chai.should();


var app = rewire('../application/application.js');


var logError = app.__get__('logMongoError'); 

describe('Application module', function() {

  it('should output the correct error', function(done) {
      logError().should.equal('MongoDB Connection Error. Please make sure that MongoDB is running.');
      done();
  });
});

诀窍是将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模块计算文件,但这不起作用,并抛出一个错误,指出exports未定义。

你可以使用vm模块创建一个新的上下文,并对其中的js文件进行eval,有点像repl。然后你就可以访问它声明的所有内容。

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

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

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在任何地方,你使用它作为测试。myInternalFn和在生产中它是不导出的。

我一直在使用一种不同的方法,没有任何依赖: 有一个包含我想测试的所有本地函数的__testing导出,该值取决于NODE_ENV,因此它只在测试中可访问:

// file.ts
const localFunction = () => console.log('do something');
const localFunciton2 = () => console.log('do something else');
export const exportedFunction = () => {
    localFunction();
    localFunciton2();
}
export const __testing = (process.env.NODE_ENV === 'test') ? {
    localFunction, localFunction2
} : void 0;

// file.test.ts
import { __testing, exportedFunction } from './file,ts'
const { localFunction, localFunction2 } = __testing!;
// Now you can test local functions