Node + Express のルーターをテストする
なんかいろいろ基本的なとこからわかってないなぁと最近思う。
ので、自分のできないとこ、できるようになったとこを当たり前のことでも書き残していきたいなぁと思ったので、これからしばらく基礎に立ち返りつつ、日記書くように努力してみます。
とりあえず、node + express でサーバたてたときに個人的には最初の方に必要になるルーター部分のテスト。
使うもの
- テスト対象(Node で書いた HTTP エンドポイント)
- supertest
- mocha(gulp + gulp-mocha)
やり方
node というのは、本当に素晴らしいエコシステムで何かしようと思えば、誰かがたいていよくできたライブラリを作成してくれて、npm (および github)で公開してくれている。
ルーター周りのテストしたい場合には、visionmedia さん作の supertest 使えばいいとわかってしまえば、そんなにつまづくポイントは無いのかな?
mocha とどう組み合わせるかとかみたいなとこは、はじめは悩ましかった気もする。
supertest の導入
こんな感じでテスト対象となる app.js を読み込んであげれば対象サーバが起動してても起動してなくてもテストできる。
- テストコード
var request = require('supertest'); var app = require('../app'); describe('/', function() { it('home 画面が表示されること', function(done) { request(app) .get('/') .expect('Content-Type', 'text/html') .expect(200, done); }); });
- gulpfile.js の設定
var gulp = require('gulp'); var mocha = require('gulp-mocha'); gulp.task('test', function() { return gulp.src('./test/**/*.js') .pipe(mocha()); });
"scripts": { "start": "node ./bin/www", "test": "gulp test" }, "dependencies": { :
post とかで form 送信したい場合
supertest の README をよく見るとのってるけど、supertest のリクエスト部分は同じく visionmedia さんの superagent を使用している。
なので、リクエストどうやって送信しようと迷った時は、上記 superagent のドキュメントを見るとのってる。
たとえば、Form で POST されるのを前提としたログイン API をテストしたい場合。
it('ログインに成功した場合 / にリダイレクトされること', (done) => { request(app) .post('/login') .type('form') .send({email: 'test@example.com'}) .send({passwd: 'password'}) .expect('Content-Type', 'text/plain; charset=utf-8') .expect('Location', '/') .expect(302, done); });
passport と組み合わせたテスト
余談だけど、Node.js で認証ライブラリ使おうってなると passport.js が多いんじゃないかなと思う。
認証入れた途端に既存のテストがのきなみ NG に!!!
なんてなるかどうかはともかく、passport 用のスタブライブラリとして、 passport-stub が使いやすい。
こんな感じで、before
でテストのはじめに、スタブさんに適当にログインしたことにしておいてね!
ってお願いするだけで、認証部分をすっとばしてくれるので、認証に関連しない部分のテストがシンプルにできる。
ルーター部分のテストには欠かせないステキライブラリ。
var request = require('supertest'); var app = require('../../app'); var passportStub = require('passport-stub'); describe('/', () => { before(function() { passportStub.install(app); passportStub.login({email: 'test@example.com'}); }); it('home 画面が表示されること', (done) => { request(app) .get('/') .expect('Content-Type', 'text/html; charset=utf-8') .expect(200, done); }); });