mocha-chrome + chaiでJavascriptの単体テストコードを書く(3)

非同期処理のテストコードは以下の通りです。
Javascriptで"非同期"といえば"Ajax"でしょうから、以下のサンプルはlivedoorお天気Webサービス からAjaxJSONデータをGETしその妥当性を検証するテストコードを実装してみました。
livedoorお天気WebサービスJSONP未対応なのでJSON2JSONPサービスを併用)

<html><head>
    <meta charset="UTF-8">
    <link href="node_modules/mocha/mocha.css" rel="stylesheet" /> <!-- テスト結果表示用のCSS -->
    <script src="node_modules/mocha/mocha.js"></script> <!-- mochaの読込み -->
    <script src="node_modules/chai/chai.js"></script> <!-- chaiの読込み -->
</head><body>
    <div id="mocha"></div> <!-- テスト結果表示領域の確保 -->

    <script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script> <!-- jQuery -->
    <script> /* テスト対象コード */
    function getWeather(city, callback) {
        $.getJSON(
            'http://json2jsonp.com/?url=http://weather.livedoor.com/forecast/webservice/json/v1%3Fcity='
            + city + '&callback=?',
            function (data) {
                console.log(data);
                callback(data);
            });
    };
    </script>
    <script> /* テストコード */
        // 初期化
        mocha.setup('bdd');
        expect = chai.expect;

        // ここにテストコードを書く
        describe('getWeather test', function() {
            this.timeout(5 * 1000);    // 非同期タイムアウトを5秒に設定
            
            describe('test1', function() {
                it('should return "東京" when getCity("130010", )', function(done) {    // done指定=非同期テスト
                    getWeather('130010', function(res) {
                        expect(res.location.city).to.be.equal('東京');
                        done();    //非同期完了待ち
                  });
                });
            });
            describe('test2 - わざとNG', function() {
                it('should return "秋田" when getCity("020010", )', function(done) {
                    getWeather('020010', function(res) {
                        expect(res.location.city).to.be.equal('秋田');
                        done();
                  });
                });
            });
        });

        // 単体テストの実行
        mocha.run();
    </script>
</body></html>

テストコードで前回と違うところは、

  • it()の第2引数であるコールバック関数に引数"done"が追加されている
  • テスト終了時にdone()を実行する

の2点です。

                it('should return "東京" when getCity("130010", )', function(done) {    // done指定=非同期テスト
                    getWeather('130010', function(res) {
                        expect(res.location.city).to.be.equal('東京');
                        done();    //非同期完了待ち
                });

この2点を追加するだけで非同期処理のテストを正常に行えるようになります。
逆にいうと、これを忘れるとテスト結果が正常に得られない(本当はNGなのにOKと判定されることがある)のに注意してください。

また、非同期処理のタイムアウト

            this.timeout(5 * 1000);    // 非同期タイムアウトを5秒に設定

という感じで指定します。なお、

  • 規定値は2秒
  • テスト毎に異なるタイムアウトを指定することも可能

です。詳細はTimeouts - Mochaを参照してください。