テスト用にエクスプレスアプリにshouldjsとmochaを追加しましたが、アプリケーションをテストする方法を知りたいと思っています。私はこのようにしたいと思います:
app = require '../app'
routes = require '../src/routes'
describe 'routes', ->
describe '#show_create_user_screen', ->
it 'should be a function', ->
routes.show_create_user_screen.should.be.a.function
it 'should return something cool', ->
routes.show_create_user_screen().should.be.an.object
もちろん、そのテストスイートの最後のテストは、res.render関数(show_create_user_screen内で呼び出されます)が未定義であることをmedに伝えるだけです。おそらく、サーバーが実行されておらず、構成が行われていないためです。だから私は他の人がどのようにテストを設定するのだろうか?
OK、最初にルーティングコードをテストすることはしたいこともしたくないこともありますが、一般的には、使用しているExpressやフレームワークから切り離された純粋なJavaScriptコード(クラスまたは関数)で興味深いビジネスロジックを分離しようとします。バニラモカテストを使用してテストします。 mochaで設定したルートを実際にテストする場合は、mock req, res
パラメーターをミドルウェア関数に渡して、express/connectとミドルウェア間のインターフェースを模倣する必要があります。
簡単なケースでは、次のようなres
関数を使用してモックrender
オブジェクトを作成できます。
describe 'routes', ->
describe '#show_create_user_screen', ->
it 'should be a function', ->
routes.show_create_user_screen.should.be.a.function
it 'should return something cool', ->
mockReq = null
mockRes =
render: (viewName) ->
viewName.should.exist
viewName.should.match /createuser/
routes.show_create_user_screen(mockReq, mockRes).should.be.an.object
また、FYIミドルウェア関数は特定の値を返す必要はありません。req, res, next
パラメーターを使用して実行するので、テストで焦点を合わせる必要があります。
コメントでリクエストしたJavaScriptを次に示します。
describe('routes', function() {
describe('#show_create_user_screen', function() {
it('should be a function', function() {
routes.show_create_user_screen.should.be.a["function"];
});
it('should return something cool', function() {
var mockReq = null;
var mockRes = {
render: function(viewName) {
viewName.should.exist;
viewName.should.match(/createuser/);
}
};
routes.show_create_user_screen(mockReq, mockRes);
});
});
});
connect.jsはスイートをテストします で代替を見つけました
supertest を使用して、サーバーをポートにバインドせずに、モックアップを使用せずに接続アプリをテストしています。
次に、connectの静的ミドルウェアテストスイートからの抜粋を示します(テストランナーとしてmochaを使用し、アサーションのスーパーテストを使用します)。
var connect = require('connect');
var app = connect();
app.use(connect.static(staticDirPath));
describe('connect.static()', function(){
it('should serve static files', function(done){
app.request()
.get('/todo.txt')
.expect('contents', done);
})
});
これは高速アプリでも機能します
SuperTestを試すと、サーバーの起動とシャットダウンが処理されます。
var request = require('supertest')
, app = require('./anExpressServer').app
, assert = require("assert");
describe('POST /', function(){
it('should fail bad img_uri', function(done){
request(app)
.post('/')
.send({
'img_uri' : 'foobar'
})
.expect(500)
.end(function(err, res){
done();
})
})
});
mochaには、bddテスト用にbefore、beforeEach、after、afterEachが付属しています。この場合、describe呼び出しの前に使用する必要があります。
describe 'routes' ->
before (done) ->
app.listen(3000)
app.on('connection', done)
ヘルパーおよびヘルパーHTTPクライアントとして使用するTestServerクラスを設定し、実際のHTTPサーバーに実際のリクエストを行うのが最も簡単であることがわかりました。ただし、代わりにこのようなものをモックしてスタブしたい場合があります。
// Test file
var http = require('the/below/code');
describe('my_controller', function() {
var server;
before(function() {
var router = require('path/to/some/router');
server = http.server.create(router);
server.start();
});
after(function() {
server.stop();
});
describe("GET /foo", function() {
it('returns something', function(done) {
http.client.get('/foo', function(err, res) {
// assertions
done();
});
});
});
});
// Test helper file
var express = require('express');
var http = require('http');
// These could be args passed into TestServer, or settings from somewhere.
var TEST_Host = 'localhost';
var TEST_PORT = 9876;
function TestServer(args) {
var self = this;
var express = require('express');
self.router = args.router;
self.server = express.createServer();
self.server.use(express.bodyParser());
self.server.use(self.router);
}
TestServer.prototype.start = function() {
var self = this;
if (self.server) {
self.server.listen(TEST_PORT, TEST_Host);
} else {
throw new Error('Server not found');
}
};
TestServer.prototype.stop = function() {
var self = this;
self.server.close();
};
// you would likely want this in another file, and include similar
// functions for post, put, delete, etc.
function http_get(Host, port, url, cb) {
var options = {
Host: Host,
port: port,
path: url,
method: 'GET'
};
var ret = false;
var req = http.request(options, function(res) {
var buffer = '';
res.on('data', function(data) {
buffer += data;
});
res.on('end',function(){
cb(null,buffer);
});
});
req.end();
req.on('error', function(e) {
if (!ret) {
cb(e, null);
}
});
}
var client = {
get: function(url, cb) {
http_get(TEST_Host, TEST_PORT, url, cb);
}
};
var http = {
server: {
create: function(router) {
return new TestServer({router: router});
}
},
client: client
};
module.exports = http;