如何使用nock截取请求,无论其内容如何

时间:2019-06-05 13:38:18

标签: javascript node.js testing mocha nock

我正在尝试在测试中使用nock来拦截我从Node.js的本机https模块发出的请求调用。 I'm using Promise.all向外部服务器发出两个请求。我希望我的测试拦截呼叫,并检查一些表单字段以确保它们按我的意愿填写。

我在下面设置了我的课程(保留了代码中最相关的部分):

const archiver = require('archiver');
const { generateKeyPairSync } = require('crypto');
const FormData = require('form-data');
const fs = require('fs');
const https = require('https');

class Platform {
  constructor() {
    this.FILESTORE_USERNAME = process.env.FILESTORE_USERNAME;
    this.FILESTORE_PASSWORD = process.env.FILESTORE_PASSWORD;
  }

  store(serviceName) {
    const { publicKey, privateKey } = this._generateKeys();

    return Promise.all([this._postKey(publicKey), this._postKey(privateKey)])
      .then(() => {
        return this._zipKeys(publicKey, privateKey, serviceName);
      })
      .catch((err) => {
        throw err;
      });
  }

  _postKey(key) {
    const options = this._getOptions();
    const keyName = (key.search(/(PUBLIC)/) !== -1) ? 'publicKey' : 'privateKey';
    const form = new FormData();
    form.append('file', key);
    form.append('Name', keyName);
    form.append('MimeMajor', 'application');
    form.append('MimeMinor', 'x-pem-file');
    form.append('Extension', (keyName == 'publicKey') ? 'pub' : '');
    form.append('FileClass', 'MFS::File');
    options.headers = form.getHeaders();
    options.headers.Authorization = 'Basic ' + Buffer.from(this.FILESTORE_USERNAME + ':' + this.FILESTORE_PASSWORD).toString('base64');

    return new Promise((resolve, reject) => {
      let post = https.request(options, (res) => {
        let data = '';
        if (res.statusCode < 200 || res.statusCode > 299) {
          reject(new Error('File Storage API returned a status code outside of acceptable range: ' + res.statusCode));
        } else {
          res.setEncoding('utf8');
          res.on('data', (chunk) => {
            data += chunk;
          });

          res.on('error', (err) => {
            reject(err);
          });

          res.on('end', () => {
            if (data) {
              resolve(JSON.parse(data));
            } else {
              resolve();
            }
          });
        }
      });
      post.on('error', (err) => {
        reject(err);
      });
      form.pipe(post);
      post.end();

    });
  }

  _getOptions() {
    return {
      hostname: 'api.example.com',
      path: '/media/files/',
      method: 'POST',
    };
  }
}

module.exports = Platform;

然后,我的测试代码如下所示。我正在使用摩卡,西农,柴,西农和诺克。

const Platform = require('/usr/src/app/api/Services/Platform');
const crypto = require('crypto');
const fs = require('fs');
const nock = require('nock');
const yauzl = require('yauzl');

describe('Platform', function() {
  let platform;
  beforeEach(() => {
    platform = new Platform();
  });
  afterEach(() => {
    const list = fs.readdirSync('/usr/src/app/api/Services/data/');
    list.forEach((file) => {
      fs.unlink('/usr/src/app/api/Services/data/' + file, (err) => {
        if (err) throw err;
      });
    });
    nock.cleanAll();
  });
  after(() => {
    nock.restore();
  });
  describe('store', function() {
    it('should post each generated key to an external storage place', async function() {
      this.timeout(5000);
      // const stub = sinon.stub(platform, '_postKey').resolves();
      const scope = nock('https://api.example.com')
        .persist()
        .post('/media/files/', (body) => {
          // console.log(body);
        })
        .reply(200);

      let serviceName = 'test';
      let actual = await platform.store(serviceName)
        .catch((err) => {
          (() => { throw err; }).should.not.throw();
        });

      console.log(scope);
      // expect(stub.callCount).to.equal(2);
      expect(actual).to.be.a('string');
      expect(actual).to.include(serviceName + '.zip');
      // stub.reset();

    });
  });
});

我遇到的问题是运行测试时抛出的此错误:

  

AssertionError:预期[Function]不会抛出错误,而是'Error:   Nock:与请求{\ n“ method”:“ POST”,\ n“ url”:不匹配:   “ https://api.example.com/media/files/”,\ n“标题”:{\ n
  “ content-type”:“多部分/表单数据;   boundary = -------------------------- 363749230271182821931703“,\ n
  “ authorization”:“基本abcdef1224u38454857483hfjdhjgtuyrwyt =” \ n},\ n   “身体”:   “ ---------------------------- 363749230271182821931703 \ r \ n内容处置:表单数据;名称= \”文件\“ \ r \ n \ r \ n ----- BEGIN PUBLIC   KEY ----- \ nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq + QnVOYVjbrHIlAEsEoF \ nZ4sTvqiB3sJGwecNhmgrUp9U8oqgoB50aW6VMsL71ATRyq9b3vMQKpjbU3R2RcOF \ na6mlaBtBjxDGu2nEpGX ++ mtPCdD9HV7idvWgJ3XS0vGaCM // 8ukY + VLBc1IB8CHC \ nVj + 8YOD5Y9TbdpwXR + 0zCaiHwwd8MHIo1kBmQulIL7Avtjh55OmQZZtjO525lbqa \ nWUZ24quDp38he2GjLDeTzHm9z1RjYJG6hS + Ui0s2xRUs6VAr7KFtiJmmjxPS9 / VZ \ nwQyFcz / R7AJKoEH8p7NE7nn / onbybJy + SWRxjXVH8afHkVoC65BiNoMiEzk1rIsx \ ns92woHnq227JzYwFYcLD0W + TYjtGCB8 + KS + QRIiV0pFJ3ja5VFIxjn9MxLntWcf2 \ nhsiYrmfJlqmpW1DMfZrtt41cJUFQwt7CpN72aix7btmd / q0syh6VVlQEHq / 0nDky \ nItv7dqyqZc9NNOMqK9 / kXWhbq5cwS21mm + kTGas5KSdeIR0LH7uVtivB + LKum14e \ nRDGascZcXZIVTbOeCxA6BD7LyaJPzXmlMy4spXlhGoDYyVRhpvv2K03Mg7ybiB4X \ nEL1oJtiCFkRX5LtRJv0PCRJjaa3UvfyIuz8bHK4ANxIZqcwZwER + g02gw8iqNfMa \ nDWXpfMJUU8TQuLGWZQaGJc8CAwEAAQ == \ n ----- END   上市   KEY ----- \ n \ r \ n ---------------------------- 363749230271182821931703 \ r \ nContent-Disposition:form-数据;   name = \“ Name \” \ r \ n \ r \ npublicKey \ r \ n ---------------------------- 363749230271182821931703 \ r \ nContent-Disposition:表单数据;   名称= \“ MimeMajor \” \ r \ n \ r \ n应用程序\ r \ n ---------------------------- 363749230271182821931703 \ r \ nContent-Disposition:表单数据;   名称= \“ MimeMinor \” \ r \ n \ r \ nx-pem文件\ r \ n --------------------------- -363749230271182821931703 \ r \ nContent-Disposition:表单数据;   名称= \“扩展名\” \ r \ n \ r \ npub \ r \ n ---------------------------- 363749230271182821931703 \ r \ nContent-Disposition:表单数据;   名称= \“ FileClass \” \ r \ n \ r \ nMFS :: File \ r \ n ---------------------------- 363749230271182821931703-\ r \ n“ \ n}'   被扔了

我认为这是因为Nock希望我伪造尸体以请求获得正确的比赛吗?有没有一种方法可以查找针对该地址的请求,而无论其正文如何,因此我可以自己进行测试或进行其他任何操作。

1 个答案:

答案 0 :(得分:1)

当Nock Scope的post方法传递第二个参数时,它用于与请求的正文进行匹配。

Docs for specifying the request body

在测试中,您要传递一个函数作为第二个参数,但不返回true,因此Nock不会将其视为匹配项。

从文档中

  

功能:nock将评估提供请求正文的功能   对象作为第一个参数。如果应将其视为   匹配

由于您的目标是在请求中声明表单字段,因此,最好的方法是将函数保留在此处,在// console.log(body);行所在的位置进行声明,但在行尾添加return true;功能。

您还可以返回truefalse,具体取决于您的表单字段是否与您的断言相匹配,但是根据我的经验,它会使测试的错误输出变得复杂。我更喜欢使用标准的chai expect()调用,并在Nock继续进行请求匹配之前让断言冒泡错误。