立即禁用单个 nock 范围以重新设置模拟 URL

JHH*_*JHH 5 mocha.js node.js nock

使用nock,有没有办法禁用单个 nock 范围?我一直在努力处理一些与其他测试设置相同 URL 的 nocks 的测试。它们都单独运行良好,但是当在同一个摩卡会话中运行时,其中一个会失败,因为我无法重新锁定活动的诺克范围,这意味着设置的诺克会捕获所有请求。

我尝试过的:

  • 如果我设置了一些 nocks,before()然后调用scope.persist(false)my after(),它只会“取消保留”范围,以便它可以再处理一个请求。它不会立即禁用它。
  • 我发现nock.cleanAll()立即禁用箭尾,以便可以再次设置它们,但它也会禁用可能已设置一次的任何全局箭尾,这对所有测试用例都是通用的。

到目前为止,我发现的唯一解决方案是 1) 对所有 nock 使用唯一的 URL:s,这并不总是可能的,或者 2) 使用 nock.cleanAll() 并且不依赖任何全局 nock - 相反,确保只在局部函数中设置 nock before(),包括为每个需要它们的测试重复设置全局函数。

能够做到这一点似乎非常有用

scope = nock('http://somewhere.com').persist().get('/'.reply(200, 'foo');

然后在一堆测试中使用那个箭尾,最后做

scope.remove();

但是,我一直无法做这样的事情。是否可以?

例子:

before(async () => {
   nock('http://common').persist().get('/').reply(200, 'common');
});

after(async () => {
});

describe('Foo tests', () => {
    let scope;
    before(async () => {
        scope = nock('http://mocked').persist().get('/').reply(200, 'foo');
    });
    after(() => {
        // scope.persist(false); // This causes the Bar tests to use the Foo nocks one more time :(
        // nock.cleanAll(); // This also disables the common nocks
    });
    it('Should get FOO', async () => {
        expect(await fetch('http://mocked').then(res => res.text())).to.equal('foo');
        expect(await fetch('http://common').then(res => res.text())).to.equal('common');
    });
    it('Should get FOO again', async () => {
        expect(await fetch('http://mocked').then(res => res.text())).to.equal('foo');
        expect(await fetch('http://common').then(res => res.text())).to.equal('common');
    });
});

describe('Bar tests', () => {
    let scope;
    before(async () => {
        scope = nock('http://mocked').persist().get('/').reply(200, 'bar');
    });
    after(() => {
        // scope.persist(false);
        // nock.cleanAll();
    });
    it('Should get BAR', async () => {
        expect(await fetch('http://mocked').then(res => res.text())).to.equal('bar');
        expect(await fetch('http://common').then(res => res.text())).to.equal('common');
    });
    it('Should get BAR again', async () => {
        expect(await fetch('http://mocked').then(res => res.text())).to.equal('bar');
        expect(await fetch('http://common').then(res => res.text())).to.equal('common');
    });
});
Run Code Online (Sandbox Code Playgroud)

如果使用,这些测试要么使第三个测试失败scope.persist(false)(因为该测试仍然获取 foo 版本),要么如果使用,则使测试 3 和 4 失败nock.cleanAll(),因为公共诺克随后被删除。

小智 1

我也遇到了这个问题,并找到了一种方法来解决它,方法是侦听request范围发出的事件并在事件触发时删除拦截器。理想情况下,我认为您应该监听该replied事件,但由于某种原因,当我尝试时该事件没有触发,不知道为什么。但下面的代码对我有用:

/**
 * @jest-environment node
 */

const nock = require('nock');

describe('Test suite', () => {

  test('Test case', async () => {

    let interceptor1 = nock('https://example-url.com', {
        reqHeaders: {
          'Content-Type': 'text/xml',
          soapaction: 'http://www.sample.com/servie/getOrders',
        },
      })
      .post('/');

    let interceptor2 = nock('https://example-url.com', {
        reqHeaders: {
          soapaction: 'http://www.sample.com/servie/getProducts',
        },
      })
      .post('/');

    let scope = interceptor1.replyWithFile(200, path.join(__dirname, './path1.xml'));
    interceptor2.replyWithFile(200, path.join(__dirname, './path.xml'));

    scope.on('request', (req, interceptor) => {
      nock.removeInterceptor(interceptor1);
    });

    const resp = await asynccall();
    expect(resp).toStrictEqual(exp);
  });

});
Run Code Online (Sandbox Code Playgroud)