15

是否可以对闭包中存在的 javascript 函数进行单元测试,例如,给定以下内容:

(function() {
  var a = function() {
    //do something
  }
  window.b =  function() {
    // do something else
  }
})();

是否可以对函数 a 进行单元测试而不暴露它?如果没有,是否有一种很好的方法来公开 a,但只能在测试模式下?

4

3 回答 3

8

您的匿名函数可以接受一个在未处于测试模式时未定义的参数,并说该参数将是一个对象,您可以用a's 填充该对象而不直接暴露a

只是我的 .02$

于 2011-07-08T14:54:34.887 回答
3

这里最大的问题是你为什么要隐藏它?您拥有想要测试的函数 a 的事实表明 a 有自己的责任应该被测试。在权衡暴露它的最小风险时,将其拉出并进行测试会获得更多价值。如果您真的想隐藏它,那么我建议您使用类似于 Manux 的响应的方法,在该响应中创建一个对象,该对象执行 a 所做的操作但不直接公开 a。然后您可以通过测试该对象来测试 a 的行为。

于 2011-07-08T15:58:48.753 回答
1

四年后重新审视这个问题,我现在有了一个更好的解决方案。

生成代码的可测试版本作为构建步骤。

假设我正在使用 Gulp 来缩小我的 JavaScript,我的代码如下所示:

var a = function() {}
window.b = function() {}

不是没有关闭。现在我设置了一个 gulp 任务并让它监视我的代码,如下所示:

gulp.task('js', function () {
  return gulp.src([dirs.js.src, '*.js'].join('/'))
    .pipe(wrap('(function() {\n<%= contents %>\n})();'))
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(gulp.dest(dirs.js.dest));
});

这会将我的代码包装在 IIFE 中,产生以下输出:

(function() {
var a = function() {}
window.b = function() {}
)();

生成可测试版本

现在我添加另一个 Gulp 任务,像这样

gulp.task('testJs', function () {
  return gulp.src([dirs.test.src, '*.js'].join('/'))
    .pipe(wrap(
      [
        '(function() {',
          '<%= contents %>',
          '// Smuggle locals out of closure for testing',
          'window.a = a;',
        '})();'
      ].join('\n')
    ))
    .pipe(concat(package.name + '.testable.js'))
    .pipe(gulp.dest(dirs.test.dest));
});

这将在我的测试目录中生成以下不安全但可测试的代码:

(function() {
var a = function() {}
window.b = function() {}
// Smuggle locals out of closure for testing
window.a = a;
)();

添加监视任务...

gulp.task('watch', function() {
  gulp.watch([dirs.js.src, '**', '*.js'].join('/'), ['js', 'testJs']);
});

...你就完成了。

看这里

请参阅此处的示例:

https://github.com/forwardadvance/ng-tweets

于 2015-07-02T14:13:09.233 回答