我正在尝试了解如何开发独立的JavaScript代码。我想编写带有命令行运行的测试和模块的Javscript代码。所以我已经安装了 node.jsnpm 与图书馆一起 requirejs, underscore, , 和 mocha.

我的目录结构看起来像这样:

> tree .
.
├── node_modules
├── src
│   └── utils.js
└── test
    └── utils.js

在哪里 src/utils.js 是我正在编写的一个小模块,并附有以下代码:

> cat src/utils.js 
define(['underscore'], function () {

    "use strict";

    if ('function' !== typeof Object.beget) {
        Object.beget = function (o) {
            var f = function () {
            };
            f.prototype = o;
            return new f();
        };
    }

});

test/utils.js 是测试:

> cat test/utils.js 
var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['../src/utils'], function(utils) {

    suite('utils', function() {
        test('should always work', function() {
            assert.equal(1, 1);
        })
    })

});

然后,我尝试从顶级目录运行(所以 mocha 看到 test 目录):

> mocha

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: Calling node's require("../src/utils") failed with error: ReferenceError: define is not defined
    at /.../node_modules/requirejs/bin/r.js:2276:27
    at Function.execCb (/.../node_modules/requirejs/bin/r.js:1872:25)
    at execManager (/.../node_modules/requirejs/bin/r.js:541:31)
    ...

所以我的问题是:

  • 这是构造代码的正确方法吗?
  • 为什么我的测试不运行?
  • 学习这种东西的最佳方法是什么?我很难与Google一起找到好的例子。

谢谢...

对不起 - 暂时发布了错误代码的结果;现在修复了

ps我正在使用requirejs,因为我还想从浏览器中运行此代码(或其中的某些代码)。

更新 /解决方案

以下答案中没有的东西是我需要使用 mocha -u tdd 对于上面的测试样式。这是最终测试(也需要断言)及其使用:

> cat test/utils.js 

var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['../src/utils', 'assert'], function(utils, assert) {

    suite('utils', function() {
        test('should always work', function() {
            assert.equal(1, 1);
        })
    })

});
> mocha -u tdd

  .

  ✔ 1 tests complete (1ms)
有帮助吗?

解决方案

您的测试不进行的原因是因为 src/utils.js 不是有效的node.js库。

根据requirejs文档,为了与node.js共存,commonj需要标准,您需要 添加一点样板 到你的顶部 src/utils.js 归档,所以requirejs的 define 功能已加载。

但是,由于“ requirejs”旨在能够需要“经典”以Web浏览器为导向的源代码,因此我倾向于使用我的node.js库中使用以下模式,我也希望在浏览器中运行:

if(typeof require != 'undefined') {
    // Require server-side-specific modules
}

// Insert code here

if(typeof module != 'undefined') {
    module.exports = whateverImExporting;
}

这具有不需要其他node.js用户的额外库,并且通常可以与客户端上的requienj一起使用。

在Node.js中运行代码后,您可以开始测试。即使它是继任测试框架,我个人仍然更喜欢摩卡咖啡。

其他提示

关于如何设置这些东西的摩卡咖啡文档缺乏,由于引擎盖下的所有魔术,这令人困惑。

我找到了使用使用浏览器文件的密钥 require.js 在节点下在摩卡咖啡工作:摩卡 将文件添加到套件中 addFile:

mocha.addFile('lib/tests/Main_spec_node');

其次,使用 beforeEach 带有可选回调以使您的模块不同步:

describe('Testing "Other"', function(done){
    var Other;
    beforeEach(function(done){
        requirejs(['lib/Other'], function(_File){
            Other = _File;
            done(); // #1 Other Suite will run after this is called
        });
    });

    describe('#1 Other Suite:', function(){
        it('Other.test', function(){
            chai.expect(Other.test).to.equal(true);
        });
    });
});

我创建了一个bootstrap,用于如何使这一切工作: https://github.com/clubajax/mocha-bootstrap

您正在尝试运行为浏览器设计的JS模块(AMD),但是在后端,它可能行不通(因为模块是以CONCORJS方式加载的)。因此,您将面临两个问题:

  1. 定义未定义
  2. 0测试运行

在浏览器中define 将定义。当您需要使用requirejs的东西时,它将设置。但是nodejs加载模块以commonjs方式。 define 在这种情况下,未定义。但是,当我们需要requirejs时,它将定义!

这意味着现在我们要求代码异步,并且带来了第二个问题,即ASYNC执行的问题。https://github.com/mochajs/mocha/issues/362

这是一个完整的工作示例。看,我必须配置requirejs(AMD)来加载模块,我们不使用require(node/commonj)来加载模块。

> cat $PROJECT_HOME/test/test.js

var requirejs = require('requirejs');
var path = require('path')
var project_directory = path.resolve(__dirname, '..')

requirejs.config({
  nodeRequire: require, 
  paths: {
    'widget': project_directory + '/src/js/some/widget'
  }
});

describe("Mocha needs one test in order to wait on requirejs tests", function() {
  it('should wait for other tests', function(){
    require('assert').ok(true);
  });
});


requirejs(['widget/viewModel', 'assert'], function(model, assert){

  describe('MyViewModel', function() {
    it("should be 4 when 2", function () {
        assert.equal(model.square(2),4)
    })
  });

})

以及您要测试的模块:

> cat $PROJECT_HOME/src/js/some/widget/viewModel.js

define(["knockout"], function (ko) {

    function VideModel() {
        var self = this;

        self.square = function(n){
            return n*n;
        }

    }

    return new VideModel();
})

以防万一 大卫的答案 还不够清楚,我只需要添加它:

if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

到我使用的JS文件的顶部 define, ,如requirejs文档中所述(“使用AMD或requirejs构建节点模块”),在同一文件夹中添加 amdefine 包裹:

npm install amdefine

这创建了 node_modules 带有的文件夹 amdefine 内部模块。

我不使用 requirejs 所以我不确定该语法是什么样的,但这是我在内部运行代码的方法 nodebrowser:

对于导入,请确定我们是在节点还是浏览器中运行:

var root =  typeof exports !== "undefined" && exports !== null ? exports : window;

然后,我们可以正确获取任何依赖项(如果在浏览器中或我们使用 require):

var foo = root.foo;
if (!foo && (typeof require !== 'undefined')) {
    foo = require('./foo');
}

var Bar = function() {
    // do something with foo
}

然后,其他文件需要使用的任何功能,我们将其导出为root:

root.bar = Bar;

至于示例, GitHub 是一个很好的来源。只需去查看您喜欢的图书馆的代码,以查看他们是如何做到的:)我使用了 mocha 测试可以在浏览器和节点中使用的JavaScript库。该代码可在 https://github.com/bunkat/later.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top