web-dev-qa-db-ja.com

node.jsのデータベースのモッキング?

Node.jsアプリケーションでデータベースをモックアウトするにはどうすればよいですか?この場合、ブログのバックエンドとしてmongodbを使用しますREST API?

もちろん、データベースを特定のtestingデータベースに設定できますが、データを保存し、コードだけでなくデータベースもテストするため、実際には単体テストではなく統合テストを実行しています。
では、何をすべきでしょうか?アプリケーションとデータベースの間の中間層としてデータベースラッパーを作成し、テスト時にDALを置き換えますか?

// app.js  
var express = require('express');
    app = express(),
    mongo = require('mongoskin'),
    db = mongo.db('localhost:27017/test?auto_reconnect');

app.get('/posts/:slug', function(req, res){
    db.collection('posts').findOne({slug: req.params.slug}, function (err, post) {
        res.send(JSON.stringify(post), 200);
    });
});

app.listen(3000);

// test.js
r = require('requestah')(3000);
describe("Does some testing", function() {

  it("Fetches a blogpost by slug", function(done) {
    r.get("/posts/aslug", function(res) {
      expect(res.statusCode).to.equal(200);
      expect(JSON.parse(res.body)["title"]).to.not.equal(null);
      return done();
    });

  });
));
68
Industrial

データベース関連のコードは、データベースソフトウェアでテストしなければ適切にテストできるとは思いません。これは、テストするコードがJavaScriptだけでなく、データベースクエリ文字列でもあるためです。あなたの場合、クエリは単純に見えますが、永遠にそのように頼ることはできません。

そのため、データベースエミュレーションレイヤーは、必然的にデータベース全体を実装します(おそらくディスクストレージを差し引く)。それまでに、単体テストと呼んでも、データベースエミュレータとの統合テストを行うことになります。別の欠点は、データベースエミュレーターがデータベースとは異なるバグのセットを持つことになり、データベースエミュレーターとデータベースの両方をコーディングする必要が生じる可能性があることです(IE vs Firefox vs Chromeなど)。

したがって、私の意見では、コードを正しくテストする唯一の方法は、実際のデータベースとインターフェイスすることです。

109
slebetman

Ock笑に関しては、一般的な経験則があります。

自分が所有していないものをm笑しないでください。

データベースをモックアウトしたい場合は、抽象化されたサービスレイヤーを非表示にし、そのレイヤーをモックします。次に、実際のサービスレイヤーを統合テストします。

個人的には、テストにモックを使用するのをやめて、トップからボトムの設計に使用して、上から下に向かってサービスレイヤーをモックアウトし、最終的にそれらのレイヤーを実装して統合テストを作成するのに役立ちます。テストツールとして使用すると、テストが非常に脆くなる傾向があり、最悪の場合、実際の動作とモックされた動作との間に相違が生じます。

40
christkv

これまでのところ、選択した回答やその他の回答に同意しません。

QAに到達する前に、DBスキーマとコードに加えられた混andとした何度も厄介な変更によって生じたエラーをキャッチできたら素晴らしいと思いませんか?私は大多数がそう叫ぶだろうに違いない!

DBスキーマを分離してテストすることができます。また、エミュレーターや重いイメージ、またはDBとマシンの再作成に基づいてそれを行うことはありません。これは、SQLiteのようなものが1つの例にすぎないことです。実行中のメモリ内軽量インスタンスとメモリインスタンス内で変化しない静的データに基づいてモックを作成します。つまり、DBを単独でテストし、テストも信頼できることを意味します。そして明らかに、それはメモリ、スケルトンにあり、テスト実行の終了時に破棄されるため、高速です。

そのため、使用するDBエンジン/ランタイムの非常に軽量なメモリインスタンスにエクスポートされるSCHEMAをテストする必要があります。また、非常に少量の静的データを追加すると、孤立した模擬DBになります。

定期的に(自動化された方法で)実際のDBから実際のスキーマをエクスポートし、QAにプッシュする前に、それらをメモリ内のDBインスタンスにインポート/更新します。DB管理者またはその他の人がDB最近スキーマを変更した開発者はテストを壊しました。

最善を尽くして答えようと努力していることを称賛しますが、できれば現在の答えに賛成票を投じますが、私はまだ新しく、まだ自分の能力を発揮できるほどの評判を築いていません。

「あなたが所有していないものをm笑してはいけない」と答えた人については。彼は「あなたが所有していないものをテストしないでください」と言うつもりだったと思う。しかし、あなたは自分が所有していないものをm笑します!それらは、テストする必要のないもので、隔離する必要があるからです!

このHOWを皆さんと共有する予定であり、この投稿を将来の時点で実際のJSコードの例で更新します!

これは、多くのテスト駆動チームが常に行うことです。方法を理解する必要があります。

36
PositiveGuy

任意の言語でDBコードを単体テストするための私が好むアプローチは、リポジトリの抽象化を通じてMongoにアクセスすることです(ここに例があります http://iainjmitchell.com/blog/?p=884 )。実装は、公開されるDB固有の機能の点で異なりますが、独自のロジックからすべてのMongoコードを削除することにより、ユニットテストを行うことができます。 Mongo Repositoryの実装を、非常に簡単なスタブアウトバージョンに置き換えるだけです。たとえば、単純なメモリ内ディクショナリコレクションにオブジェクトを保存するだけです。

この方法でDBに依存せずに独自のコードを単体テストするメリットは得られますが、実際のデータベースの特異性を他のユーザーが持つようにエミュレートすることはおそらくできないため、メインDBに対して統合テストを行う必要がありますここで言った。私が見つけた種類のものは、セーフモードでインデックスを作成するのと同じくらい簡単です。具体的には、一意のインデックスがある場合、ダミーメモリの実装はすべての場合にそれを尊重する可能性がありますが、Mongoはセーフモードを使用します。

そのため、一部の操作についてはデータベースに対してテストする必要がありますが、スタブ化されたリポジトリ実装を使用して、独自のロジックを適切に単体テストできます。

4
cirrus

モックの目的は、複雑さをスキップし、独自のコードを単体テストすることです。 e2eテストを作成する場合は、dbを使用します。

ユニットテスト用にテストDBをセットアップ/分解するためのコードを書くことは、技術的な負債であり、信じられないほど不満です。

Npmにはモックライブラリがあります。

mongo- https://www.npmjs.com/package/mongomock

mongoose- https://www.npmjs.com/package/mockgoose

それらが必要な機能をサポートしていない場合、はい、あなたは本物を使用する必要があるかもしれません。

4
Michael Cole

私はこのジレンマを抱えていたため、テストDBで作業し、テストが開始されるたびにクリーンアップすることを選択しました。 (すべてをドロップする方法: https://stackoverflow.com/a/25639377/378594

NPMを使用すると、dbファイルを作成し、後でクリーンアップするテストスクリプトを作成することもできます。

2
Uri