在这个使用supertest和Node.js的testing中,res.body是空的

我正在用supertesttesting一个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 })); 

这是我正在testing的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方法执行的testing:

 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: {}, ... 

基于以下testing,您期待“application / vnd.burgers.api + json; charset = utf-8'作为Content-Type:

 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不会自动为你parsing这个JSON。 内容types头文件必须以string“application / json”开始。 如果你不能做到这一点,那么你将不得不使用JSON.parse函数来将该文本string转换为对象。

supertest使用这个文件来确定你是否发送json。 supertest实际上启动你的express服务器,通过HTTP做出一个请求,并迅速closures它。 在HTTP切换之后,那个HTTP请求的客户端(基本上是superagent )不知道你的服务器configuration关于'application / vnd.burgers.api + json; 字符集= UTF-8' 。 它所知道的只是通过头文件告知的,在这种情况下是内容types。

另外,我确实在我的机器上尝试了自定义标题,并且还有一个空的主体。

编辑:更新的表格链接,如评论中所述

这是旧的,但它帮助我如此想我可以分享一些知识。

以math为例,我发现这些信息实际上是在res.text中,而不是res.body。

我最后添加了一些特殊的处理:

 if(res.headers['content-type'] == 'myUniqueContentType' && res.body===undefined){ res.body = JSON.parse(res.text); } 

我的问题是.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(); }); 

 app.use(bodyParser.json({ type: 'application/*+json' })) 

这将接受所有的json内容types:-)