question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nock affects other test cases with different URLs

See original GitHub issue

What is the expected behavior? Nock should differentiate URL parameters.

What is the actual behavior? Nock does not differentiate URL params and affects other test cases.

Possible solution

Does the bug have a test case? I have two separate it cases included in a single describe. The first tests is for a case when everything goes fine:

const ips = ['1.2.3.4', '11.12.13.14'];

it('should return successfully resolved geolocation', async () => {
  const cacheKey = `${ips[0]}_${locale}`;

  nock('https://www.travelpayouts.com')
    .get('/whereami')
    .query({ locale, ip: ips[0] })
    .reply(200, exampleResult);

  redisGetMock.mockResolvedValueOnce(null);
  redisSetMock.mockResolvedValueOnce('OK');

  const result = await getUserGeo(ips[0]);

  expect(redisGetMock).toHaveBeenCalledWith(cacheKey);
  expect(redisSetMock).toHaveBeenCalledWith(
    cacheKey,
    JSON.stringify(exampleResult),
    'EX',
    864000, // 10 days
  );

  expect(result).toStrictEqual(exampleResult);
});

And then I have a test case for a failing version of my function:

it('should fallback to default response body on got error', async () => {
  const cacheKey = `${ips[1]}_${locale}`;

  nock('https://www.travelpayouts.com')
    .get('/whereami')
    .query({ locale, ip: ips[1] })
    .reply(500, 'Internal Server Error');

  redisGetMock.mockResolvedValueOnce(null);

  const result = await getUserGeo(ips[1]);

  expect(redisGetMock).toHaveBeenCalledWith(cacheKey);
  expect(redisSetMock).not.toHaveBeenCalled();
  expect(result).toStrictEqual({
    coordinates: '37.617633:55.755786',
    country_name: 'Россия',
    iata: 'MOW',
    name: 'Москва',
  });
});

The problem here is that the second test will always fail because sindresorhus/got returns 200 OK instead of 500 Internal Server no matter what. So why is this happens? Because the URLs are different:

  1. https://www.travelpayouts.com/whereami?locale=ru&ip=1.2.3.4
  2. https://www.travelpayouts.com/whereami?locale=ru&ip=11.12.13.14

But if I put failing test before a regular one then everything goes just fine and all tests are passing. If I remove nock config with 500 error then test will also fail and request will match for nock 200 config.

Versions

Software Version(s)
Nock 13.0.5
Node 12.18.4
TypeScript 4.0.3

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mastermattcommented, Dec 8, 2020

The problem here is that the second test will always fail because sindresorhus/got returns 200 OK instead of 500 Internal Server no matter what. So why is this happens? Because the URLs are different…

This is the part that is causing to me scratch my head.

Couple of questions:

0reactions
qmg-rwallercommented, Jul 15, 2021

@mastermatt I’m not familiar with reading nock debug logs but are three requests made? I only see two ... attempting match ... and matching X to GET Y lines.

I notice that for the 2nd request, there are these lines:

nock.intercept matched base path (1 interceptor) +1ms
...
nock.scope:www.travelpayouts.com attempting match ...
...
nock.socket socket destroy +45ms // why destroy now?
nock.request_overrider socket close +10ms
...
nock.intercept matched base path (0 interceptor) // where did the above interceptor go?
nock.intercept using 0 interceptors +0ms
nock.request_overrider request end +1s
nock.request_overrider ending +0ms
nock.socket socket destroy +1s
nock.request_overrider socket close +2ms

why does the nock.socket socket destroy twice, and why is there at first 1 interceptor, then 0 interceptors?

edit I’ve noticed that if the request times out, it can cause a premature nock.socket socket destroy. If the request client retries the request, there will be 0 interceptors because the first was already used up. However I don’t know if that’s your issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nock is not working with multiple test cases with same method
node. js - Nock is not working with multiple test cases with same method - Stack Overflow. Stack Overflow for Teams – Start...
Read more >
Mocking External HTTP Requests in Node Tests with Nock
Avoid the challenges of testing Node.js code that depends on external services and APIs by using Nock to test HTTP requests in isolation....
Read more >
Mocking Dependencies in Integration Tests with Nock
Nock matches urls exactly without regex, and any calls that are unmatched are unhandled and throw an error. Query parameter bypass nock("https ...
Read more >
How to Test External APIs with Nock - The New Stack
A response from axios is far different from a request response, so nock allows the user to see how the agent handles situations...
Read more >
Nock it out of the park, HTTP mocking for React - ITNEXT
Nock is used to mocking calls to HTTP. It makes it possible for us to specify what URLs to listen to and what...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found