【问题标题】:How to use nock to intercept requests regardless of body如何使用 nock 拦截请求而不考虑 body
【发布时间】:2019-06-05 13:38:18
【问题描述】:

我试图在我的测试中使用 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;

然后,我的测试代码如下所示。我正在使用 mocha、sinon、chai、sinon-chai 和 nock。

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
“内容类型”:“多部分/表单数据; 边界=--------------363749230271182821931703",\n
"授权": "基本 abcdef1224u38454857483hfjdhjgtuyrwyt="\n },\n “身体”: "----------------363749230271182821931703\r\n内容配置:表单数据;名称=\"文件\"\r \n\r\n-----开始公开 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=\"名称\"\r\n\r\npublicKey\r\n----------------------------363749230271182821931703\r \n内容配置:表单数据; name=\"MimeMajor\"\r\n\r\n应用程序\r\n----------------------------363749230271182821931703\r \n内容配置:表单数据; name=\"MimeMinor\"\r\n\r\nx-pem-file\r\n--------------------------- -363749230271182821931703\r\n内容配置:表单数据; name=\"扩展名\"\r\n\r\npub\r\n----------------------------363749230271182821931703\r \n内容配置:表单数据; name=\"FileClass\"\r\n\r\nMFS::File\r\n---------------------------- 363749230271182821931703--\r\n"\n}' 被扔了

我认为这是因为 nock 希望我伪造身体以获得正确匹配的请求?有没有办法只查找对该地址发出的请求,而不考虑正文,所以我可以自己进行测试或其他任何事情。

【问题讨论】:

    标签: javascript node.js testing mocha.js nock


    【解决方案1】:

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

    Docs for specifying the request body

    在您的测试中,您将函数作为第二个参数传递,但没有返回 true,因此 Nock 不认为它匹配。

    来自文档:

    函数:nock 将评估提供请求正文的函数 对象作为第一个参数。如果它应该被认为是 匹配

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

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

    【讨论】:

      猜你喜欢
      • 2019-07-14
      • 2019-09-19
      • 2016-10-05
      • 2017-06-19
      • 1970-01-01
      • 2019-09-26
      • 2017-02-28
      • 1970-01-01
      • 2011-04-03
      相关资源
      最近更新 更多