requireJを使用してMochaテストを実行するときに、なぜ「定義されていない」と表示されるのですか?
-
25-10-2019 - |
質問
スタンドアロンの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)
...
だから私の質問は次のとおりです。
- これはコードを構築する正しい方法ですか?
- なぜ私のテストが実行されていないのですか?
- この種のことを学ぶための最良の方法は何ですか? 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と共存するには、commonjsが標準を要求するためには、 少しのボイラープレートを追加します あなたの一番上に src/utils.js
ファイルso 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ユーザーに追加のライブラリを必要としないという利点があり、通常、クライアントのrequirejsとうまく機能します。
node.jsでコードを実行したら、テストを開始できます。私は個人的には、後継者のテストフレームワークであるにもかかわらず、MochaよりもExpressoを好む。
他のヒント
Mochaのドキュメントには、このようなものを設定する方法が不足しており、ボンネットの下で行うすべての魔法のトリックのために把握するのは困惑しています。
ブラウザファイルを使用して使用するキーを見つけました require.js ノードの下でMochaで働く:Mocha もっている スイートにファイルを追加します 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);
});
});
});
これをすべて機能させる方法のブートストラップを作成しました: https://github.com/clubajax/mocha-bootstrap
ブラウザ用に設計されたJSモジュール(AMD)を実行しようとしていますが、バックエンドでは機能しない可能性があります(モジュールがCommonJSの方法でロードされるため)。このため、2つの問題に直面します。
- 定義は定義されていません
- 0テストが実行されます
ブラウザでdefine
定義されます。必要なものが必要なときに設定されます。ただし、nodejsはモジュールをcommonjsの方法でロードします。 define
この場合、定義されていません。ただし、requirejsを使用して必要なときに定義されます!
これは、今ではコードを非同期的に必要としていることを意味し、2番目の問題、非同期実行の問題をもたらします。https://github.com/mochajs/mocha/issues/362
これが完全な作業例です。モジュールをロードするためにrequirejs(AMD)を構成する必要があるように見えますが、モジュールをロードするために要求(ノード/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();
})
念のため デビッドの答え 十分に明確ではなかったので、これを追加する必要がありました:
if (typeof define !== 'function') {
var define = require('amdefine')(module);
}
私が使用しているJSファイルの上部に define
, 、requirejs docsで説明されているように(「AMDまたはrequireJを使用したノードモジュールの構築」)そして同じフォルダーに追加します amdefine
パッケージ:
npm install amdefine
これは、を作成します node_modules
のフォルダー amdefine
内部モジュール。
私は使用しません requirejs
だから、その構文がどのように見えるかはわかりませんが、これは私が両方でコードを実行するために行うことです node
そしてその browser
:
インポートについては、ノードで実行されているかブラウザで実行しているかを判断します。
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.bar = Bar;
たとえば、 GitHub
素晴らしい情報源です。お気に入りのライブラリのコードをチェックして、彼らがどのようにしたかを確認してください:)私は使用しました mocha
ブラウザとノードの両方で使用できるJavaScriptライブラリをテストします。コードはで利用できます https://github.com/bunkat/later.