84

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

もちろん、データベースを特定のtesting-database に設定することもできますが、それでもデータを保存し、コードだけでなくデータベースもテストするので、実際には単体テストではなく統合テストを行っています。
では、何をすべきでしょうか?アプリケーションとデータベースの間の中間層としてデータベース ラッパーを作成し、テスト時に 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();
    });

  });
));
4

6 に答える 6

137

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

したがって、データベース エミュレーション レイヤーは、必然的にデータベース全体を実装します (おそらくディスク ストレージを除く)。それまでに、単体テストと呼んでいても、データベース エミュレーターとの統合テストを行うことになります。もう 1 つの欠点は、データベース エミュレーターにはデータベースとは異なる一連のバグが発生する可能性があり、データベース エミュレーターとデータベースの両方のコーディングが必要になる可能性があることです (IE と Firefox と Chrome などの状況に似ています。 )。

したがって、私の意見では、コードを正しくテストする唯一の方法は、それを実際のデータベースに接続することです。

于 2012-09-21T08:17:44.317 に答える
46

モッキングに関しては、一般的な経験則があります。

あなたが所有していないものを嘲笑しないでください。

データベースをモックアウトする場合は、抽象化されたサービス レイヤーの背後に隠して、そのレイヤーをモックします。次に、実際のサービス層の統合テストを行ってください。

個人的には、モックをテストに使用することから離れて、トップからボトムへの設計にモックを使用することで、上から下に向かって開発を推進し、サービス レイヤーをモックアウトして、最終的にそれらのレイヤーを実装し、統合テストを記述しています。テストツールとして使用すると、テストが非常に脆弱になる傾向があり、最悪の場合、実際の動作とモックされた動作との相違につながります。

于 2012-09-25T09:39:56.113 に答える
44

選択した回答または他の回答に同意しません。

QA に入る前に、DB スキーマとコードに行われた無秩序で何度も厄介な変更によって生成されたエラーを検出できたら素晴らしいと思いませんか? 私は大多数がイエスと叫ぶに違いない!

DBスキーマを分離してテストすることは間違いなく可能であり、そうすべきです。また、エミュレーターや重いイメージ、DB とマシンの再作成に基づいてそれを行うこともありません。これは、ほんの一例として、SQLite のようなものです。実行中のメモリ内軽量インスタンスに基づいてモックし、メモリ内インスタンスで変更されない静的データを使用します。つまり、DB を分離して真にテストしており、テストも信頼できます。そして、明らかに高速です。これは、メモリ内のスケルトンであり、テスト実行の最後に破棄されるためです。

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

実際の DB から定期的に (自動化された方法で) 実際のスキーマをエクスポートし、QA にプッシュするたびにそれらをライト イン メモリ DB インスタンスにインポート/更新すると、DB 管理者またはその他のユーザーによって最新の DB が変更されたかどうかがすぐにわかります。最近スキーマを変更した開発者は、すべてのテストに違反しています。

最善を尽くして答えようとする努力に拍手を送りますが、できれば現在の答えに反対票を投じますが、私は新しく、まだそうする能力を有効にするのに十分な評判をまだ築いていません。

「あなたが所有していないものをあざけるな」と答えた人に関しては。「所有していないものはテストしないでください」という意味だったと思います。しかし、あなたは自分が所有していないものを嘲笑します! それらは分離する必要があるテスト対象ではないものだからです!

HOW を皆さんと共有する予定であり、将来的にこの記事を実際の JS コードの例で更新する予定です!

これは、多くのテスト駆動型チームが常に行っていることです。方法を理解するだけです。

于 2015-05-26T23:56:59.840 に答える
5

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

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

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

于 2012-09-30T09:39:29.410 に答える