首页 > 解决方案 > nodejs 模块中 UMD 块的代码覆盖率

问题描述

我用 UMD(通用模块定义)模式编写了一个节点模块,以使其与 amd 和普通 javascript 兼容。

定义如下

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.myModule = factory();
    }
}(this, function (global) {
    ...
    return {};
}));

使用 mocha & chai 测试运行良好,唯一的问题是由于测试是从节点内执行的,因此代码覆盖率define(factory);root.myModule = factory();行显示为红色。

只是想知道是否有任何方法(可能是 hack)使用 mocha chai 获得 100% 的代码覆盖率。

标签: node.jsmocha.jscode-coveragenode-moduleschai

解决方案


当然!

JS 的覆盖工具基本上是如何工作的,就是它们为每一行注入一点跟踪代码。所以你需要的是那里的执行流程奇迹。

由于这是一个if-else逻辑,因此100%您将需要多个测试场景来涵盖这一点。

注意:对于实际实现此效果也很重要,加载该文件 ( factory) 应该在每个场景设置之后发生,因为那是module-loading-if-else执行这些行的时间。现在这取决于您在测试执行环境中加载的文件/模块是什么。

现在进入branch创建if-else测试场景,您可以define通过几行(例如在一个beforeEach部分中)强制执行该功能的存在:

define = function () {
  console.log('hello I am a fake define, but I will be defined ...');
  console.log(' ... so that if else branch will be executed.');
}

// and of course the needed .amd property.
define.amd = true;

我认为可以用exports变量完成同样的奇怪事情,但如果你只是纯粹的 CommonJS -ing 那个文件可能很难实现require,因为require-ing 定义了exports那个文件上下文的变量,所以也许你可以修改你的生产这个奇怪案例的代码。我不会那样做,但你说any way

...
 } else if (typeof exports === 'object' && testExportsEnabled) {
...

现在使用这个你可以有一个场景beforeEach:如果testExportsEnabled = true;这是错误的,最后一个分支应该被执行。

当然,你可以用这样一个简单的技巧来执行所有的分支!现在没有代码修改并触发第三个分支(基本上是script-tag-loading浏览器中简单的情况),您需要深入了解您的模块加载代码并在那里创建一些黑客,但这对我来说有点太多了 SO问题!:]

小心!


推荐阅读