Имитация объекта запроса Express.JS multipart / form-data

Я хотел бы провести модульное тестирование функции промежуточного программного обеспечения Express, которая, в свою очередь, использует node-formidable для обработки загрузка составного файла.

Вот надуманный пример:

function doUpload(req, res, next) {
    const form = new formidable.IncomingForm();
    form.uploadDir = this.mediaDir;
    form.keepExtensions = true;
    form.type = 'multipart';
    form.multiples = true;

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        res.end(util.inspect({fields: fields, files: files}));
    });
}

Этот код у меня работает при тестировании с Chrome и работающим приложением Express.

Я хочу, чтобы мой тестовый код выглядел так, как показано ниже, где я имитирую объект запроса, но я не могу понять, как имитировать объект запроса с данными формы. Грозный обратный вызов не срабатывает:

it(‘handles uploads’, (done) => {
    const mockReq = http.request({
        host: 'example.org',
    });
    mockReq.url = ‘/upload’;

    const res = jasmine.createSpyObj('response', [ 'json', 'send', 'status', 'render', 'header', ‘redirect’, ‘end’, ‘write;]);
    const next = jasmine.createSpy('next');

    //*how to emulate a request with a multipart file upload)

    doUpload(req, res, next);
    res.write.and.callFake(done);
});

Я пробовал использовать библиотеку form-data, чтобы создать объект FormData и передать его в просьба, но не повезло, я не уверен, на правильном ли я пути или ухожу. Что-то вроде этого:

var form = new FormData();

const buff = fs.readFileSync(path.join(__dirname, '../fixtures/logo.png'));

form.append('file', buff, {
    filename: 'logo.jpg',
    contentType: 'image/png',
    knownLength: buff.length
});
form.append('name', 'Logo');

req.headers = form.getHeaders();

form.pipe(req);
doUpload(req, res, next);

person Phil Mander    schedule 04.09.2016    source источник
comment
Такая же проблема здесь, я пытаюсь издеваться над запросом, который содержит данные формы.   -  person kiwicomb123    schedule 15.08.2018
comment
У меня также была проблема с этим подходом, но я обнаружил, что мне не хватало метода HTTP POST при создании фиктивного запроса. Как только это было решено, это сработало как оберег   -  person Pablo Flores    schedule 16.04.2020


Ответы (2)


Используйте комбинацию form-data и mock-express-request. Это сработало для меня:

const fs = require('fs');
const MockExpressRequest = require('mock-express-request');
const FormData = require('form-data');

const form = new FormData();
form.append('my_file',
  fs.createReadStream(path.join(__dirname, 'fixtures', 'file-upload-test.txt'))
);
const request = new MockExpressRequest({
  method: 'POST',
  host: 'localhost',
  url: '/upload',
  headers: form.getHeaders()
});

form.pipe(request);
doUpload(request, response, next);
person dmit77    schedule 09.08.2019
comment
Отличное предложение, это действительно полезный способ протестировать служебные функции, которые используют запрос Http либо из стандартной библиотеки, либо из Express, избегая необходимости выполнять вызовы Http. - person Pablo Flores; 16.04.2020

Для этого вы можете использовать какой-нибудь тестер запросов, например supertest. Вот пример, предполагающий, что ваш основной файл называется app.js:

const request = require('supertest');
const app = require('app.js');

it('Uploads a file', function(){
    request(app)
      .post('/upload')
      .field('name', 'Logo') //adds a field 'name' and sets its value to 'Logo'
      .attach('file', '/path/to/file') // attaches the file to the form
      .then(function(response){
          // response from the server
          console.log(response.status);
          console.log(response.body);
      })

})

person Juan D. Gómez    schedule 20.09.2018
comment
Хорошее предложение для модульного тестирования конечных точек Http. Супертест действительно прост в использовании. Может быть полезно сказать, что он также поддерживает синтаксис async / await - person Pablo Flores; 16.04.2020