作为一项学习练习,我正在尝试使用 Node 和 Express 运行一个版本的Bowling Game kata,但我发现了一个特殊的问题。我可以从比我更了解 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)
游戏.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);
});
});
});