2016-05-17 18 views
12

TL; DR - 認証用にJWTを使用するノードAPI(Express)のリソースをトークン自体でテストする方法ユーザー名/パスワードのログインに付与されていますか?JWT認証を使用するノードAPIをテストする方法(ユーザーログインを使用してトークンを取得する)

私は試験にちょっと新しく、助言を受けたいと思っていました。最終的な目標は、完全にテストされたAPIを用意し、それをContinuous Integrationソリューションにつなげる方法を学ぶことです。使用中の

テクノロジーズ

  • 私はエクスプレスを使用してノードにAPIを書かれています。
  • Mongoはデータベースです。
  • マングースがODMとして使用されます。
  • jsonwebtokenパッケージを使用してトークンを作成/検証します。
  • パスポートは、Expressミドルウェアとしてユーザー認証をルートに簡単に追加するために使用されます。詳細はそのうちこのクエリには重要ではありませんが、できはちょうどそれが簡単にするためのユビキタス藤堂アプリだふり -

API情報

APIは、さまざまなリソースを持っています。

データベースに保存されている個々のリソースは、1人のユーザーに関連付けられています。

APIは、さまざまなリソースエンドポイントにわたる認証にJWTを使用します。トークン自体には、Mongoデータベースのリソースに対して格納されている一意のユーザーIDが含まれています。トークン自体を取得するには、ユーザーが最初にサインアップして(トークンを返す)、ログインして新しいトークンを取得する必要があります。

偽コード。

私は...等、あらゆる環境のconfigsの使用を作る

app.js

var express = require('express'); 
var app = express(); 
var mongoose = require('mongoose'); 
var bodyParser = require('body-parser'); 
var passport = require('passport'); 

mongoose.connect('mongodb://localhost/somedatabasename'); 

app.set('port', process.env.PORT || 3000); 
app.use(bodyParser.urlencoded({ extended: true })); 
app.use(bodyParser.json()); 

app.use(passport.initialize()); 
// ... Passport JWT Strategy goes here - omitted for simplicity ... 

var userRouter = require('./api/users/routes'); 
app.use('/users', userRouter); 
var todoRouter = require('./api/todos/routes'); 
app.use('/todos', todoRouter); 

app.listen(app.get('port'), function() { 
    console.log('App now running on http://localhost:' + app.get('port')); 
}); 

./api/todos/routes.js

を以下のコードを簡素化するつもりはありませんよ
var router = require('express').Router(); 
var controller = require('./controller'); 
var passport = require('passport'); 

router.route('/') 
    .all(passport.authenticate('jwt', { session: false})) 
    .get(controller.getAll) 
    .post(controller.create); 

router.route('/:id') 
    .all(passport.authenticate('jwt', { session: false})) 
    .get(controller.getOne) 
    .put(controller.update) 
    .delete(controller.delete); 

module.exports = router; 

./api/users/routes.js

var router = require('express').Router(); 
var controller = require('./controller'); 
var passport = require('passport'); 

router.route('/') 
    // User signup 
    .post(controller.create); 

router.route('/me') 
    // User Login 
    .post(passport.authenticate('local', { session: false}), controller.login) 
    // Get current user's data 
    .get(passport.authenticate('jwt', { session: false}), controller.getOne) 
    // Update current user's data 
    .put(passport.authenticate('jwt', { session: false}), controller.update) 
    // Delete current user 
    .delete(passport.authenticate('jwt', { session: false}), controller.delete); 

module.exports = router; 

./api/users/model.js

var mongoose = require('mongoose'); 
var bcrypt = require('bcrypt'); 

var UserSchema = new mongoose.Schema({ 
    username: { 
    type: String, 
    required: true, 
    unique: true 
    }, 
    password: { 
    type: String, 
    required: true 
    } 
}); 

// ... for simplicity imagine methods here to 
// - hash passwords on a pre save hook using bcrypt 
// - compare passwords using bcrypt when logging in 

module.exports = mongoose.model('User', UserSchema); 

./api/todos/model.js

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 

var momentSchema = new Schema({ 
    title: { 
    type: String 
    }, 

    // Bunch of other fields here... 

    _user: { 
    type: Schema.Types.ObjectId, 
    ref: 'User' 
    } 
}); 

module.exports = mongoose.model('Moment', momentSchema); 

私はクリーンでシンプルな、それを維持するためのコード例の一部を省略しています。

例えば、ユーザーコントローラがモデルを含むとなるその機能になります。

  • controller.create - 新しいユーザー(戻りトークン)のためにサインアップ
  • controller.login - Passport Localによって確認されたユーザー名とパスワードの組み合わせの後に有効なトークンを返す
  • controller.getOne JWTトークンから検索されたID、MongooseからMongooseを使用してユーザーのデータを返します。
  • controller.update - 藤堂さんコントローラは似た何かをするだろうマングース

を使用してモンゴにおけるユーザーのデータを削除 - マングース

  • controller.deleteを使用してモンゴにおけるユーザーのデータを更新します - 特定の(例えば)Todoアイテムを認証されたユーザ(JWTを介して認証された)に関連付けるためのユーザIDを常に含むことになります。

    テスト難問私はモカ、チャイとSuperTestの組み合わせを使用して、このような何かをテストしに行くかどう

    は私でしょう:

    • モンゴ内テスト用のデータベースを作成し、接続文字列がテストで異なることがありますか?これは、テストのためにデータベースに格納されている実際のデータを保存することを意味します。
    • 何とかデータをモックし、テストデータベースを使用しないでください。しかし、トークンを取得するためにユーザーセーブ/ログイン処理はどのように処理されますか?

    開発中のローカルテストと、CIツールを使用してデプロイメントを行う場合のテストの違いは何ですか?

    どのような援助がはるかに高く評価されるだろうと私は、私は上記のダミーデータ/コードとの十分な情報を与えてくれた願っています:あなたはモンゴDB(mongo-mockのようなものをあざける、通常どおりテスト中/

  • +0

    こんにちは!あなたはこれを理解しましたか?私はまた、この種のテストを実装しようとしています。 –

    答えて

    1

    この方法では、

    テスト中は、mongodbmongo-mockに置き換えてテストを実行します。トークンを取得するには、テストを実行するために、実際のデータベースを実行する必要はありません(データベースはテストしていません)有効な偽装された資格証明を使用して/me URLに投稿する必要があります。そのエンドポイントはトークンを戻し、次回の呼び出しで使用します他のエンドポイントをテストします。

    物事のトークン側では、私は通常、要求の始めにそれをチェックしてから、他のエンドポイントを入力します。(私はパスポートを使用していないが、アイデアがある):トークンが無効である場合

    app.use(validate_jwt_middleware); 
    app.use('/users', userRouter); 
    

    この方法では、それがないだけで、あなたのセクション、サイト全体のために無効です。

    また、SuperTestではなく、chai-httpを使用していますので、お手数ですがお手伝いできません。

    希望します。

    関連する問題