2016-02-05 10 views
18

私はノードとエクスプレスを初めて使い、ルート/コントローラを単体テストしようとしています。私は私のルートを私のコントローラから分けました。私のルートをテストするにはどうすればいいですか?単体テストエクスプレスルータのルート

設定/ express.js

var app = express(); 
    // middleware, etc 
    var router = require('../app/router')(app); 

APP /ルーター/ index.js

module.exports = function(app) { 
    app.use('/api/books', require('./routes/books')); 
    }; 

APP /ルーター/ルート/ books.js

var controller = require('../../api/controllers/books'); 
    var express = require('express'); 
    var router = express.Router(); 

    router.get('/', controller.index); 

    module.exports = router; 

アプリ/ API /コントローラ/ books.js

// this is just an example controller 
exports.index = function(req, res) { 
    return res.status(200).json('ok'); 
}; 

アプリ/テスト/ API /ルート/ books.test.js

var chai = require('chai'); 
    var should = chai.should(); 
    var sinon = require('sinon'); 

    describe('BookRoute', function() { 

    }); 
+1

[単体テストはExpressとどのようにルートを結ぶのですか?](http://stackoverflow.com/questions/9517880/how-does-one-unit-test-routes-with-express) – gnerkus

+0

重複しないリンクされている質問は、異なるAPIを持つ古いExpress用です。 – Kos

+0

この[リンク](http://www.designsuperbuild.com/blog/unit_testing_controllers_in_express/)またはこの[リンク](http://www.chrisstead.com/archives/1128/unit-testing-express-routing/)を使用してください。 )。 –

答えて

1

は、私が見つかりました。this blog自分をテストするときに非常に洞察に満ちましたサーバーのエンドポイント。

  • をエンドポイント・テスト・ライブラリsupertestを使用する方法:彼はアドレスをブログで

  • 各エンドポイントテストの前後に必要なルートでエクスプレスサーバーをプログラムでスピンアップおよびティアダウンする方法。 (彼はなぜあなたがこれをやりたいのかを説明します)。

  • 一般的な問題を回避するには、単体テストに必要なモジュールをキャッシュする必要があり、意図しない結果が生じます。

希望します。幸運を祈って、さらに質問があれば教えてください。

+3

ブログのポイントには、supertestを使用してAPIエンドポイントをテストするための良い例がいくつかあります。しかし、私は著者に完全に同意していないので、いくつかのコメントが必要だと感じています。各テストの間にサーバーの起動と停止は間違った設計です。それがRESTfulなAPIなら、テストしているのにサーバはステートレスでなければなりません。状態のあるアプリケーションの場合は、各テスト間でセッションを破棄して同じ結果を得ることができます。また、JavaScriptスタックがどのように動作して誤った結論につながるのか、作者は理解していないようです。 –

7

コード:

設定/ express.js

var app = express(); 
// middleware, etc 
var router = require('../app/router')(app); 

module.exports = app; 

APP /試験/ API /ルート/ books.test.js

var chai = require('chai'); 
var should = chai.should(); 
var sinon = require('sinon'); 
var request = require('supertest'); 
var app = require('config/express'); 

describe('BookRoute', function() { 
    request(app) 
     .get('/api/books') 
     .expect('Content-Type', /json/) 
     .expect('Content-Length', '4') 
     .expect(200, "ok") 
     .end(function(err, res){ 
      if (err) throw err; 
     }); 
}); 

考察:

もしあなたがサーバーの状態を変更する呼び出しを実行しているので、urサーバーは一連のテストの開始時に初期状態を必要とするため、新しく構成されたアプリケーションと各テストグループの先頭を返す関数を記述する必要があります。 NPMライブラリhttps://github.com/bahmutov/really-needがあり、サーバーの新しくインスタンス化されたバージョンを要求することができます。

1

これはあなたのコントローラをルータから切り離したので興味深いです。コメントに記載されている他のStackOverflow記事は、あなたのコントローラをテストするための良い方法だと思います。ユニットテストで念頭に置くべきことは、あなたが正確にテストしていることです。エクスプレスライブラリをテストするためのテストを書く必要はありません。おそらく、独自のユニットテストがあるからです。したがって、ライブラリへの呼び出しをテストするだけです。だから、本のルートのために、あなただけのコードのこの1行をテストする必要があります。

router.get('/', controller.index); 

を「私が急行ライブラリからルートのリストを取得するための明確な方法があったかどうかを確認するために周りを見回したが、私はdidnの1つを見てください。おそらくライブラリ自体を見て、内部をチェックしてルートを正しく設定しているかどうかを調べることができます。しかしもう一つの選択肢は、それを模擬して、それを正しく呼んでいるかどうかをチェックすることです。

これは、この1行のコードをテストするためにJavascriptの基本部分をモックアップする必要があるため、かなり複雑になります。ここで私はそれをやった方法は次のとおりです。ここで何が起こっている

describe('BookRoute', function() { 
    it("should route/to books controller index", function() { 
    var controller = require('../../../api/controllers/books'); 
    var orig_this = this; 
    var orig_load = require('module')._load; 
    var router = jasmine.createSpyObj('Router', ['get']); 
    var express = jasmine.createSpyObj('express', ['Router']); 
    express.Router.and.returnValues(router); 
    spyOn(require('module'), '_load').and.callFake(function() { 
     if (arguments[0] == 'express') { 
     return express; 
     } else { 
     return orig_load.apply(orig_this, arguments); 
     } 
    }); 
    require("../../../router/routes/books"); 
    expect(router.get).toHaveBeenCalledWith('/', controller.index); 
    }); 
}); 

は私が必要とするコールのすべてを処理するものであるmodule.jsで_load機能をspyOnするジャスミンのspyOn機能を使用しています。これは、書籍のルーターが必要なときにrequire( 'express')を呼び出すと、jasmine.createSpyObjで作成したExpress SpyObjを返すことができるようになります。 expressをSpyオブジェクトに置き換えたら、ルータのSpyObjを返すようにして、router.getを偵察することができます。次に、それが '/'とcontroller.indexで呼び出されていることを確認することができます。

これは、これをたくさん使いたければ、多分何らかのユーティリティーにすることができます。

私は通常、よりオブジェクト指向のアプローチを使用して多くのことを避けています。私はテストのためにモックできるいくつかのオブジェクトを渡していますか、角度使用のような何らかの依存性注入を使用できます。

関連する問題