Немедленно отключите одну область действия nock, чтобы повторно настроить фиктивный URL-адрес.

Используя nock, есть ли способ отключить одну область nock? Я боролся с некоторыми тестами, которые устанавливали ноки того же URL-адреса, что и некоторые другие тесты. Оба они работают нормально по отдельности, но при запуске в одном и том же сеансе mocha один из них дает сбой, потому что я не могу повторно зафиксировать активные области nock, что означает, что настроенные nock перехватывают все запросы.

Что я пробовал:

  • Если я настрою несколько ноков в before(), а затем вызову scope.persist(false) в своем after(), это только «отменит сохранение» области, так что она будет активна для еще одного запроса. Это не сразу отключает его.
  • Я обнаружил, что nock.cleanAll() немедленно отключает узлы, чтобы их можно было настроить снова, но затем он также отключает все глобальные узлы, которые могли быть настроены один раз, что является общим для всех тестовых случаев.

До сих пор единственными решениями, которые я нашел, являются: 1) использовать уникальные URL-адреса для всех ноков, что не всегда возможно, или 2) использовать nock.cleanAll() и не полагаться ни на какие глобальные ноки - вместо этого убедитесь, устанавливать ноки только в локальных before() функциях, в том числе повторно настраивать глобальные для каждого теста, который в них нуждается.

Кажется, было бы очень полезно иметь возможность сделать

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

а затем использовать этот nock в куче тестов и, наконец, сделать

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');
    });
});

Эти тесты либо не проходят 3-й тест при использовании scope.persist(false) (поскольку этот тест по-прежнему получает версию foo), либо не проходят тесты 3 и 4 при использовании nock.cleanAll(), поскольку в этом случае общие стыки удаляются.


person JHH    schedule 14.01.2020    source источник


Ответы (3)


У меня также была эта проблема, и я нашел способ обойти ее, прослушивая событие 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);
  });

});
person laide    schedule 24.04.2020

Как описано здесь: Невозможно удалить перехватчики с помощью nock. Я нашел способ не сохранять перехватчики, просто снова установив макет ( который, по-видимому, снова возвращает перехватчик), а затем использует возвращенный перехватчик в функции removeInterceptor(). Это действительно возвращает true и работает в моих тестах.

person Elias    schedule 19.10.2020

Я нашел довольно простой обходной путь для этого — у области есть свойство, называемое перехватчиками, которое представляет собой массив различных перехватчиков, используемых областью. Вы можете заменить свойство body перехватчика на все, что захотите.

let scope = nock(base).get(path).reply(200, []).persist();
testable.call(path).then(console.log);      //returns []
scope.interceptors[0].body = [1,2,3];
testable.call(path).then(console.log);      //returns [1,2,3]
person Andrew Long    schedule 02.03.2021