我试图了解如何开发独立的Javascript代码。我想编写带有测试和模块的Javscript代码,从命令行运行。所以我已经安装了node.js
和npm
以及库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)
...
所以我的问题是:
...谢谢
[抱歉 - 暂时发布错误代码的结果;现在修复]
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)
答案 0 :(得分:18)
您的测试未运行的原因是因为src/utils.js
不是有效的Node.js库。
根据RequireJS文档,为了与Node.js和CommonJS require标准共存,您需要add a bit of boilerplate到src/utils.js
文件的顶部,以便RequireJS的{{1}函数已加载。
然而,由于RequireJS旨在能够要求“经典”面向Web浏览器的源代码,我倾向于使用我想在浏览器中运行的Node.js库使用以下模式:
define
这样做的好处是不需要为其他Node.js用户提供额外的库,并且通常可以在客户端上使用RequireJS。
在Node.js中运行代码后,即可开始测试。我个人仍然更喜欢表达摩卡,尽管它是后继测试框架。
答案 1 :(得分:4)
Mocha文档缺乏如何设置这些内容,并且由于它在幕后所做的所有魔术技巧而难以弄清楚。
我找到了使用 require.js 在节点下的Mocha中使用浏览器文件的关键:Mocha 已将文件添加到{{1 }}:
addFile
第二,使用mocha.addFile('lib/tests/Main_spec_node');
和可选的回调来异步加载模块:
beforeEach
我创建了一个关于如何使这一切正常工作的引导程序:https://github.com/clubajax/mocha-bootstrap
答案 2 :(得分:1)
您正在尝试运行为浏览器(AMD)设计的JS模块,但在后端它可能不起作用(因为模块以commonjs方式加载)。因此,您将面临两个问题:
将在浏览器define
中定义。当你需要带有requirejs的东西时它会被设置。但是nodejs以commonjs的方式加载模块。在这种情况下,define
未定义。但是当我们需要requirejs时它将被定义!
这意味着现在我们需要异步代码,它带来了第二个问题,即异步执行问题。 https://github.com/mochajs/mocha/issues/362
这是一个完整的工作示例。 看看我必须配置requirejs(amd)来加载模块,我们没有使用require(node / commonjs)来加载我们的模块。
> 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();
})
答案 3 :(得分:0)
如果David's answer不够明确,我只需要添加:
if (typeof define !== 'function') {
var define = require('amdefine')(module);
}
在我使用define
的js文件的顶部,如RequireJS docs("Building node modules with AMD or RequireJS")中所述,并在同一文件夹中添加amdefine
包:
npm install amdefine
这将创建node_modules
模块,其中包含amdefine
模块。
答案 4 :(得分:-1)
我不使用requirejs
因此我不确定该语法是什么样的,但这是我在node
和browser
内运行代码所做的工作:< / p>
对于导入,请确定我们是在节点还是浏览器中运行:
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。