我正在使用supertest测试Node.js API,我无法解释为什么res.body
对象超集返回为空。数据显示在res.text
对象中,但不显示res.body
,是否知道如何解决此问题?
我正在使用Express和body-parser
:
app.use(bodyParser.json());
app.use(bodyParser.json({ type: jsonMimeType }));
app.use(bodyParser.urlencoded({ extended: true }));
以下是我正在测试的API方法:
app.get(apiPath + '/menu', function(req, res) {
var expiration = getExpiration();
res.set({
'Content-Type': jsonMimeType,
'Content-Length': jsonTestData.length,
'Last-Modified': new Date(),
'Expires': expiration,
'ETag': null
});
res.json({ items: jsonTestData });
}
以下是我针对此API方法执行的测试:
describe('GET /menu', function() {
describe('HTTP headers', function() {
it('responds with the right MIME type', function(done) {
request(app)
.get(apiPath + '/menu')
.set('Accept', 'application/vnd.burgers.api+json')
.expect('Content-Type', 'application/vnd.burgers.api+json; charset=utf-8')
.expect(200, done);
});
it('responds with the right expiration date', function(done) {
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0,0,0,0);
request(app)
.get(apiPath + '/menu')
.set('Accept', 'application/vnd.burgers.api+json; charset=utf-8')
.expect('Expires', tomorrow.toUTCString())
.expect(200, done);
});
it('responds with menu items', function(done) {
request(app)
.get(apiPath + '/menu')
.set('Accept', 'application/vnd.burgers.api+json; charset=utf-8')
.expect(200)
.expect(function (res) {
console.log(res);
res.body.items.length.should.be.above(0);
})
.end(done);
});
});
});
我收到的失败:
1) GET /menu HTTP headers responds with menu items:
TypeError: Cannot read property 'length' of undefined
at /Users/brian/Development/demos/burgers/menu/test/MenuApiTest.js:42:25
at Test.assert (/Users/brian/Development/demos/burgers/menu/node_modules/supertest/lib/test.js:213:13)
at Server.assert (/Users/brian/Development/demos/burgers/menu/node_modules/supertest/lib/test.js:132:12)
at Server.g (events.js:180:16)
at Server.emit (events.js:92:17)
at net.js:1276:10
at process._tickDomainCallback (node.js:463:13)
最后,这里是console.log(res)
:
...
text: '{"items":[{"id":"1","name":"cheeseburger","price":3},{"id":"2","name":"hamburger","price":2.5},{"id":"3","name":"veggie burger","price":3},{"id":"4","name":"large fries","price":2},{"id":"5","name":"medium fries","price":1.5},{"id":"6","name":"small fries","price":1},{"id":"7","name":"large drink","price":2.5},{"id":"8","name":"medium drink","price":2},{"id":"9","name":"small drink","price":1}]}',
body: {},
...
答案 0 :(得分:6)
基于以下测试,您期待'application / vnd.burgers.api + json; charset = utf-8'作为内容类型:
request(app)
.get(apiPath + '/menu')
.set('Accept', 'application/vnd.burgers.api+json')
.expect('Content-Type', 'application/vnd.burgers.api+json; charset=utf-8')
.expect(200, done);
此快速路由还显示您将标头设置为某个自定义值jsonMimeType:
app.get(apiPath + '/menu', function(req, res) {
var expiration = getExpiration();
res.set({
'Content-Type': jsonMimeType,
'Content-Length': jsonTestData.length,
'Last-Modified': new Date(),
'Expires': expiration,
'ETag': null
});
res.json({ items: jsonTestData });
}
如果是这种情况,supertest将不会自动为您解析该JSON。 content-type标头必须以字符串'application / json'开头。如果你无法实现这一点,那么你必须自己使用JSON.parse函数将该文本字符串转换为对象。
supertest使用this file来确定您是否正在发送json。 supertest实际启动你的快速服务器,通过HTTP发出一个请求,然后快速关闭它。在HTTP切换之后,该HTTP请求的客户端(基本上是superagent)对于'application / vnd.burgers.api + json;的服务器配置一无所知。字符集= UTF-8' 。所有它知道的是它通过标题,在这种情况下,内容类型。
另外,我确实在我的机器上尝试了自定义标题,并且还有一个空体。
修改更新了表格链接,如评论中所述
答案 1 :(得分:0)
这已经过时了,但它让我觉得我可能会分享一些知识。
使用mattr示例,我发现该信息实际上在res.text中,而不是res.body。
我最后添加了一些特殊处理:
if(res.headers['content-type'] == 'myUniqueContentType' && res.body===undefined){
res.body = JSON.parse(res.text);
}
答案 2 :(得分:0)
我的问题是.set()
方法设置了请求标头,而.send()
将使用您指定的json数据设置请求主体。
request("/localhost:3000")
.post("/test")
.type("json")
.set({color: "red"}) //this does nothing!
.expect(200)
.end(function(res) {
done();
});
修复:
request("/localhost:3000")
.post("/test")
.type("json")
.send({color: "red"}) //fixed!
.expect(200)
.end(function(res) {
done();
});
答案 3 :(得分:-1)
添加
Step 1) Use CLLocationManagerDelegate Delegate
Step 2) Write It's Delegate Method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[self speedCalculator:locations];
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(@"%@",error.userInfo);
if([CLLocationManager locationServicesEnabled]){
NSLog(@"Location Services Enabled");
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"App Permission Denied" message:@"To re-enable, please go to Settings and turn on Location Service for this app." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil];
[alertController addAction:ok];
[self presentViewController:alertController animated:YES completion:nil];
}
}
}
-(void)speedCalculator:(NSArray *)locations
{
CLLocation *loc = locations.lastObject;
double speeds = loc.speed;
if (speeds > 0)
{
self.speedLabel.text = [NSString stringWithFormat:@"%.02f",speeds*3.6];
SpeedValue = (float) (speeds*3.6) ;
}
else
{
self.speedLabel.text = @"0.00"; // When Device is not moving the Speed Value will become -ve.
SpeedValue = 0.00 ;
}
}
这将接受所有json内容类型: - )