web-dev-qa-db-ja.com

supertestとNode.jsを使用するこのテストでは、res.bodyは空です。

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

次のテストに基づいて、 'application/vnd.burgers.api + json;を期待しています。 Content-Typeとして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は このファイル を使用して、jsonを送信しているかどうかを判断します。内部的には、supertestは実際にExpressサーバーを起動し、HTTP経由で1つのリクエストを行い、すぐにシャットダウンします。そのHTTPハンドオフの後、そのHTTPリクエストのクライアント側(基本的には superagent )は、 'application/vnd.burgers.api + jsonに関するサーバー構成について何も知りません。 charset = utf-8 '。それが知っているのは、ヘッダー(この場合はcontent-type)を介して伝えられたことだけです。

また、私は自分のマシンでカスタムヘッダーを試しましたが、本体も空になりました。

編集:コメントに記載されているようにテーブルリンクを更新しました

6
mattr

これは古いですが、それは私がいくつかの知識を共有するかもしれないと思ったので私を助けました。

Mattrの例を参考にしてみると、その情報は実際にはres.bodyではなくres.textにあることがわかりました。

私は最終的にいくつかの特別な処理を追加しました:

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

私の問題は、.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();
    });
0
Daniel Lizik