Чтение выходного буфера/потока ответа с помощью супертеста/суперагента на сервере node.js

Я пытаюсь написать тест, который проверяет, выводит ли маршрут API ZIP-файл с правильным содержимым.

Я использую mocha и supertest для тестирования, и я хотел бы на самом деле прочитать выходной поток/буфер, прочитать содержимое zip-файла и посмотреть, правильно ли содержимое.

Любые идеи, как мне это сделать? Когда я пытаюсь прочитать res.body, это просто пустой объект.

  request(app)
    .get( "/api/v1/orders/download?id[]=1&id=2" )
    .set( "Authorization", authData )
    .expect( 200 )
    .expect( 'Content-Type', /application\/zip/ )
    .end( function (err, res) {
      if (err) return done( err );

      console.log( 'body:', res.body )

      // Write the temp HTML file to filesystem using utf-8 encoding
      var zip = new AdmZip( res.body );
      var zipEntries = zip.getEntries();

      console.log( 'zipentries:', zipEntries );

      zipEntries.forEach(function(zipEntry) {
        console.log(zipEntry.toString()); // outputs zip entries information
      });

      done();
    });

person ragulka    schedule 26.11.2012    source источник


Ответы (5)


Расширяя ответ @Beau, можно использовать следующее, чтобы получить любой двоичный контент ответа в качестве буфера, который вы можете изучить далее в request.end():

function binaryParser(res, callback) {
    res.setEncoding('binary');
    res.data = '';
    res.on('data', function (chunk) {
        res.data += chunk;
    });
    res.on('end', function () {
        callback(null, new Buffer(res.data, 'binary'));
    });
}

// example mocha test
it('my test', function(done) {
    request(app)
        .get('/path/to/image.png')
        .expect(200)
        .expect('Content-Type', 'image.png')
        .buffer()
        .parse(binaryParser)
        .end(function(err, res) {
            if (err) return done(err);

            // binary response data is in res.body as a buffer
            assert.ok(Buffer.isBuffer(res.body));
            console.log("res=", res.body);

            done();
        });
});
person rcoup    schedule 10.02.2013
comment
Это прекрасно работает, хотя мне пришлось добавить .buffer() к запросу. - person Nate; 25.02.2014
comment
С помощью @Nate из документов, если буферизация ответов не включена ( .buffer(false)) , то событие ответа будет сгенерировано, не дожидаясь завершения синтаксического анализа тела, поэтому response.body будет недоступен. - person ZachB; 20.07.2016
comment
@ZachB так .buffer().parse(binaryParser)? - person rcoup; 20.07.2016
comment
@rcoup да, говорят документы, но, похоже, он отлично работает и без быстрого теста. Это может потребоваться для более длинных ответов...? - person ZachB; 20.07.2016

Я думаю, вы захотите создать свой собственный синтаксический анализатор для application/zip и использовать его для получения фактических данных ответа; анализатор JSON находится, например, здесь. Как только вы это сделаете, вы можете использовать его, передав его в request.parse; поэтому ваш тест станет:

request(app)
  .get( "/api/v1/orders/download?id[]=1&id=2" )
  .set( "Authorization", authData )
  .expect( 200 )
  .expect( 'Content-Type', /application\/zip/ )
  .parse( function (res, fn) {
    res.data = '';
    res.on( 'data', function (chunk) { res.data += chunk; } );
    res.on( 'end', function () {
      try {
        fn( null, new AdmZip( res.data ) );
      } catch ( err ) {
        fn( err );
      }
    });
  })
  .end( function (err, res) {
    if (err) return done( err );

    console.log( 'body:', res.body )

    // Write the temp HTML file to filesystem using utf-8 encoding
    var zipEntries = res.body.getEntries();

    console.log( 'zipentries:', zipEntries );

    zipEntries.forEach(function(zipEntry) {
      console.log(zipEntry.toString()); // outputs zip entries information
    });

    done();
  });

Чтобы найти ответ на этот вопрос, я в основном полагался на проверку набора тестов суперагента. :)

person Beau    schedule 21.12.2012

Существующие ответы не сработали для меня. В итоге я сделал следующее:

// parses response.body buffer into a data object
const parsePDF = response => {
  return new Promise((resolve, reject) => {
    // code that parses response.body as buffer
    // and calls resolve(data); when done
    // or reject(err); on error
  })
};

const binaryParser = require('superagent-binary-parser');

// test snippet
request(app)
    .get('/some/api/returning/pdf')
    .expect(200)
    .expect('content-type', 'application/pdf')
    .parse(binaryParser)
    .buffer()
    .then(parsePDF)
    .then((pdf) => {
      chai.expect(pdf.pages.length).to.be.equal(5);
    })
person Edi    schedule 14.10.2017

Просто у меня был тот же случай, когда мне нужно было написать тест для проверки содержимого zip-файла. Вот как я это сделал.

    it('test', async function () {
        let data = '';
        const res = await request(app)
            .get('/api/some-zip')
            .parse((res, callback) => {
                res.setEncoding('binary');
                res.on('data', function (chunk) {
                    data += chunk;
                });
                res.on('end', function () {
                    callback(null, Buffer.from(data, 'binary'));
                });
            })
        const zip = new AdmZip(res.body)
        const zipEntries = zip.getEntries();

        expect(zipEntries[0].name).to.equal('zipfile1.pdf');
        expect(zipEntries[1].name).to.equal('zipfile2.pdf');
    });

Я использовал синтаксис async/await

person David Storm    schedule 21.03.2021

Как описано в разделе Тестирование двоичного ответа с помощью супертеста, установка .responseType('blob') в запросе приведет к тому, что req.body будет Буфер.

https://visionmedia.github.io/superagent/#binary

it('test', async () => {
  await request(app)
    .get('/api/some-zip')
    .responseType('blob')
    .expect(200)
    .expect('Content-Type', /application\/zip/)
    .expect(( res) => {
      const zipEntries = new AdmZip(res.body).getEntries().map(e => e.entryName);
      expect(zipEntries).toEqual(expect.arrayContaining(['zipfile1.pdf', 'zipfile2.pdf']));
  });
});
person Boris    schedule 06.08.2021