asyncモジュールを使った非同期Nodeアプリケーションのテスト方法を模索してみました。
とりあえず以下のようにしたら動きましたが、何かツッコミあれば下さい。
まず、アプリケーションですが、
- 指定したURLの画像ファイルをダウンロードし、
- そのファイルをGoogle Driveにアップロードし、
- 新しいURLを取得する
というものです。
argFtu
で渡しているのは、まるごとftu
インスタンスそのものです。
app.js
var async = require('async');
var fileToUpload = require('./FileToUpload.js');
var ftu;
async.waterfall([
function (callback) {
/*** At first, download image file ***/
ftu = new fileToUpload.FileToUpload('http://xxx.com/xxx.jpg', callback);
},
function (argFtu, callback) {
/*** Secondary, upload the image file to Google Drive ***/
argFtu.uploadToGoogleDrive(callback);
},
function (argFtu, callback) {
console.log(argFtu.newUrl);
callback(null, 'done');
}
]);
このFileToUpload
クラスをテストします。テストのフレームワークはMocha + expect.jsです。
test.js
var fileToUpload = require('../FileToUpload.js');
var ftu;
describe('FileToUpload', function () {
beforeEach(function (done) {
var callback = function () {};
ftu = new fileToUpload.FileToUpload('http://xxx.com/xxx.jpg', callback, done);
});
it('ファイルをアップロードすることができる', function (done) {
var callback = function () {};
expect(ftu.uploadToGoogleDrive(callback, done)).to.be.a('string');
});
});
テストでは、asyncモジュール用のcallback
関数はいらないので、function () {}
を突っ込みます(もっと良い書き方があれば教えて下さい)。
それでも非同期テストのためにdone()
が残るので、FileToUpload.jsの中で無効化しています。
FileToUpload.js
...
file.on('finish', function () {
file.close(function () {
console.log('File download is done\n');
callback(null, _this); // for async module
if (done != null) {
done(); // for mocha async testing
}
});
});
...
}, function (err, response) {
_this.newUrl = response.webContentLink;
_this.newUrl = _this.newUrl.replace('&export=download', '');
callback(null, _this); // for async module
if (done != null) {
done(); // for mocha async testing
}
return _this.newUrl;
});
...
これで、アプリケーションもテストも(いちおう)正常に動きます。
ブログやっています:Weed software