2

学習課題として、Node と Express を使用して実行されているバージョンのボウリング ゲーム カタを取得しようとしていますが、特有の問題が発生しています。Node と Express を私よりもよく知っている人から、その理由を理解するための助けを借りることができます。

ストライク テスト ケースを機能させようとしてストライク テスト ケースを作成した後、コマンド ラインでmochaを使用して以下のテストを実行しようとすると、次のスーパーテスト エラーが発生します"Uncaught TypeError: undefined is not a function" at /Users/cdurfee/bitbucket/neontapir/node_modules/supertest/lib/test.js:125:21

しかし、game.js のこの一見無害な行をコメントアウトすると ( total += rolls[ball + 2];)、エラーは発生しませんが、もちろん動作は間違っています。配列の範囲外の問題だと思われますが、それを理解する良い方法がわかりません。

これは、両方のファイルの完全な内容と mocha のコンソール出力です。

08:55 $ mocha --reporter spec

  Scoring a bowling game
    gutter game
      ✓ should return 0 
    single pin game
      ✓ should return 20 
    spare
      ✓ should return 16 after spare and a 3 
    strike
      ✓ should return 24 after strike, 4 and a 3 
      1) should return 24 after strike, 4 and a 3
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
double callback!
    perfect game

  4 passing (71ms)
  1 failing

  1) Scoring a bowling game strike should return 24 after strike, 4 and a 3:
     Uncaught TypeError: undefined is not a function
      at /Users/cdurfee/bitbucket/neontapir/node_modules/supertest/lib/test.js:125:21
      at Test.Request.callback (/Users/cdurfee/bitbucket/neontapir/node_modules/supertest/node_modules/superagent/lib/node/index.js:660:30)
      at ClientRequest.<anonymous> (/Users/cdurfee/bitbucket/neontapir/node_modules/supertest/node_modules/superagent/lib/node/index.js:628:10)
      at ClientRequest.EventEmitter.emit (events.js:95:17)
      at Socket.socketErrorListener (http.js:1547:9)
      at Socket.EventEmitter.emit (events.js:95:17)
      at net.js:441:14
      at process._tickCallback (node.js:415:13)

game.js

var express = require('express');
var app = exports.app = express();

app.get('/start', function(req, res) {
    rolls = new Array();
    attempt = 0;
});

app.post('/bowl/:pins', function(req, res) {
    rolls[attempt] = parseInt(req.params.pins);
    attempt++;
});

app.get('/score', function(req, res) {
    var total = 0;
    var ball = 0;
    for (var frame = 0; frame < 10; frame++) {
        if (rolls[ball] + rolls[ball + 1] == 10) { 
            total += rolls[ball + 2]; // this line causes the double callback
        }
        total += rolls[ball] + rolls[ball + 1];
        ball += 2;
    }

    res.send(200, {score: total});
});

app.listen(process.env.PORT || 3000);

テスト/test.js

var request = require('supertest'),
    should = require('should');
var game = require('../game.js').app;

var assertScoreEquals = function(expectedScore) {   
    request(game).get('/score').expect(200).end(function(err,res) {
      should.not.exist(err);        
      result = res.body;        
      result.should.have.property('score').eql(expectedScore);      
    });  
};

var roll = function(pins) {
    request(game).post('/bowl/' + pins).end();
};

var rollMany = function(times, pins) {
    for (var i = 0; i < times; i++) {
        roll(pins);
    }
};

describe('Scoring a bowling game', function() {
  beforeEach(function() {
    request(game).get('/start').end();
  });

  describe('gutter game', function() {
        it('should return 0', function() {
            rollMany(20,0);
            assertScoreEquals(0);                       
        });
    });

    describe('single pin game', function() {
        it('should return 20', function() {
            rollMany(20,1);
            assertScoreEquals(20);          
        });
    });

    describe('spare', function() {
        it('should return 16 after spare and a 3', function() {         
            roll(6);
            roll(4); // spare
            roll(3);
            rollMany(17,0);
            assertScoreEquals(16);          
        });
    });

    // not expected to pass at the moment
    describe('strike', function() {
        it('should return 24 after strike, 4 and a 3', function() {         
            roll(10); // strike
            roll(4);
            roll(3);
            rollMany(17,0);
            assertScoreEquals(24);          
        });
    });

    // not expected to pass at the moment
    describe('perfect game', function() {
        it('should return 300', function() {    
            rollMany(12,10);
            assertScoreEquals(300);         
        });
    });         
});
4

1 に答える 1

6

前のコメントに追加

テストケースが非同期ではないこともわかりました。これはほぼ間違いなくあなたの問題です。

コールバックが必要です:done

  describe('gutter game', function() {
    it('should return 0', function(done) { // callback is provided as argument by mocha 
        rollMany(20,0);
        assertScoreEquals(0);
        done();  // This needs to be called when the test is finished, for async operations.
    });
});

多くのリクエストを実行する必要がある場合に、これにより作業が簡単になるため、スーパーテストの代わりにスーパーテストを約束どおりに使用することをお勧めします。このライブラリに加えて、おそらくbluebirdを使用すると、あなたのようなテストをより簡単にすることができます。

この要点Bluebirdには、promiseとを使用してテストを書き直しsupertest-as-promisedたものと、変更内容に関するコメントが含まれています。

于 2014-08-05T23:36:38.053 に答える