Node.js向けに作成されたアプリケーションを単体テストするためにmochaを使用しています
モジュールにエクスポートされていない関数を単体テストすることは可能かと思います。
例:
foobar.js
にこのように定義された関数がたくさんあります
function private_foobar1(){
...
}
function private_foobar2(){
...
}
パブリックとしてエクスポートされたいくつかの関数:
exports.public_foobar3 = function(){
...
}
テストケースの構造は次のとおりです。
describe("private_foobar1", function() {
it("should do stuff", function(done) {
var stuff = foobar.private_foobar1(filter);
should(stuff).be.ok;
should(stuff).....
private_foobar1
はエクスポートされないため、これは明らかに機能しません。
プライベートメソッドを単体テストする正しい方法は何ですか? mochaにはそれを行うための組み込みメソッドがありますか?
関数がモジュールによってエクスポートされない場合、モジュールの外部のテストコードによって呼び出すことはできません。これはJavaScriptの仕組みによるものであり、Mocha自体はこれを回避できません。
プライベート関数のテストが正しいことだと判断したいくつかの例では、モジュールがテストセットアップで実行されているかどうかを判断するためにチェックする環境変数を設定しました。テストセットアップで実行すると、テスト中に呼び出すことができる追加の関数がエクスポートされます。
ここでは「環境」という言葉が大まかに使用されています。それはprocess.env
またはモジュールと通信できる他の何かをチェックすることを意味するかもしれません。「あなたは今テストされています」。これをしなければならなかったインスタンスはRequireJS環境にあり、この目的でmodule.config
を使用しました。
rewire モジュールを確認してください。モジュール内のプライベート変数と関数を取得(および操作)できます。
したがって、あなたの場合、使用法は次のようになります:
var rewire = require('rewire'),
foobar = rewire('./foobar'); // Bring your module in with rewire
describe("private_foobar1", function() {
// Use the special '__get__' accessor to get your private function.
var private_foobar1 = foobar.__get__('private_foobar1');
it("should do stuff", function(done) {
var stuff = private_foobar1(filter);
should(stuff).be.ok;
should(stuff).....
プライベートメソッドをテストするための非常に良いワークフローです GoogleエンジニアのブログでPhilip Waltonが説明しています。
_
でマークします次に、ビルドタスクまたは独自のビルドシステム(例:grunt-strip-code)を使用して、本番ビルド用にこのブロックを削除します。
テストビルドはプライベートAPIにアクセスできますが、プロダクションビルドにはアクセスできません。
次のようにコードを記述します。
var myModule = (function() {
function foo() {
// private function `foo` inside closure
return "foo"
}
var api = {
bar: function() {
// public function `bar` returned from closure
return "bar"
}
}
/* test-code */
api._foo = foo
/* end-test-code */
return api
}())
そして、そのようなあなたの単調な仕事
grunt.registerTask("test", [
"concat",
"jshint",
"jasmine"
])
grunt.registerTask("deploy", [
"concat",
"strip-code",
"jshint",
"uglify"
])
後の記事で 、「プライベートメソッドのテスト」の「理由」について説明します
シンプルにしたい場合は、プライベートメンバーもエクスポートしますが、いくつかの規則でパブリックAPIから明確に分離します。 _
をプレフィックスとして付けるか、単一のprivateオブジェクトの下にネストします。
var privateWorker = function() {
return 1
}
var doSomething = function() {
return privateWorker()
}
module.exports = {
doSomething: doSomething,
_privateWorker: privateWorker
}
この目的のためにnpmパッケージを作成しました。これは役に立つかもしれません: require-from
基本的に、次の方法で非パブリックメソッドを公開します。
module.testExports = {
private_foobar1: private_foobar1,
private_foobar2: private_foobar2,
...
}
note:testExports
は、もちろんexports
を除く、任意の有効な名前にすることができます。
そして、別のモジュールから:
var requireFrom = require('require-from');
var private_foobar1 = requireFrom('testExports', './path-to-module').private_foobar1;
Internal()という名前の特別な関数を追加し、そこからすべてのプライベート関数を返します。このInternal()関数がエクスポートされます。例:
function Internal () {
return { Private_Function1, Private_Function2, Private_Function2}
}
// Exports --------------------------
module.exports = { PublicFunction1, PublicFunction2, Internal }
次のような内部関数を呼び出すことができます。
let test = require('.....')
test.Internal().Private_Function1()
私はこのソリューションが最も好きです:
@ barwinの回答に従い、rewireモジュールを使用してユニットテストを行う方法を確認しました。このソリューションが単に機能することを確認できます。
モジュールは、パブリック部分とプライベート部分の2つの部分で必要になります。パブリック関数の場合、標準的な方法でそれを行うことができます。
const { public_foobar3 } = require('./foobar');
プライベートスコープの場合:
const privateFoobar = require('rewire')('./foobar');
const private_foobar1 = privateFoobar .__get__('private_foobar1');
const private_foobar2 = privateFoobar .__get__('private_foobar2');
このテーマについて詳しく知るために、完全なモジュールテストを含む実用的な例を作成しました。テストにはプライベートスコープとパブリックスコープが含まれます。
詳細については、完全に説明している記事( https://medium.com/@macsikora/how-to-test-private-functions-of-es6-module-fb8c1345b25f )を確認することをお勧めします件名には、コードサンプルが含まれます。
これは必ずしもあなたが探している答えではないことを知っていますが、私が見つけたのは、ほとんどの場合、プライベート関数がテストする価値がある場合、独自のファイルに入れる価値があるということです。
例えば。次のように、パブリックメソッドと同じファイルにプライベートメソッドを含める代わりに...
src/thing/PublicInterface.js
function helper1 (x) {
return 2 * x;
}
function helper2 (x) {
return 3 * x;
}
export function publicMethod1(x) {
return helper1(x);
}
export function publicMethod2(x) {
return helper1(x) + helper2(x);
}
...次のように分割します:
src/thing/PublicInterface.js
import {helper1} from './internal/helper1.js';
import {helper2} from './internal/helper2.js';
export function publicMethod1(x) {
return helper1(x);
}
export function publicMethod2(x) {
return helper1(x) + helper2(x);
}
src/thing/internal/helper1.js
export function helper1 (x) {
return 2 * x;
}
src/thing/internal/helper2.js
export function helper2 (x) {
return 3 * x;
}
そうすれば、helper1
とhelper2
を簡単にテストできます。Rewireやその他の「魔法」を使用せずに(デバッグ中や、新しい同僚にとっては理解しにくいことは言うまでもなく、TypeScriptに向かって動きます。そして、それらはinternal
と呼ばれるサブフォルダー、またはそのようなものにあることで、意図しない場所での偶発的な使用を回避するのに役立ちます。
追伸:「プライベート」メソッドのもう1つの一般的な問題は、publicMethod1
およびpublicMethod2
をテストし、ヘルパーをモックしたい場合、通常はRewireのようなものが必要なことです。ただし、それらが別々のファイルにある場合、 Proxyquire を使用してそれを行うことができます。これは、Rewireとは異なり、ビルドプロセスに変更を加える必要がなく、読みやすく、デバッグが簡単で、動作しますTypeScriptでも同様です。
プライベートメソッドをテストに使用できるようにするには、次のようにします。
const _myPrivateMethod: () => {};
const methods = {
myPublicMethod1: () => {},
myPublicMethod2: () => {},
}
if (process.env.NODE_ENV === 'test') {
methods._myPrivateMethod = _myPrivateMethod;
}
module.exports = methods;