4

I'm using 3rd party API which has /places endpoint which returns the information of the places the authenticated user has permissions as JSON. That API is using JWT as authentication, the token is placed in X-Auth-Token header.

My project has a service which authenticates to that 3rd party API with multiple user accounts. One of my test cases is testing that service so that the /places gets called two times. The service authenticates to the 3rd party API and sets the token to X-Auth-Token before requesting /places.

I've tried to make a mock of the 3rd party API as follows:

nock(apiUrl)
  .matchHeaders("x-auth-token", firstToken)
  .get(/places/)
  .reply(200, placeList1);
nock(apiUrl)
  .matchHeaders("x-auth-token", secondToken)
  .get(/places/)
  .reply(200, placeList2)

But Nock throws me error that there was no match for the request. If I try

nock(apiUrl)
  .matchHeaders("x-auth-token", (value) => {
    console.log(value)
    return value === firstToken;
  })
  .get(/places/)
  .reply(200, placeList1);

I can see that the value of the X-Auth-Token is correct for one of the requests but the endpoint won't still match.

Am I doing something wrong? Or is it even possible to have multiple requests to same path of the same scope with different responses with Nock? As my service is using Promises I can't rely on the order in which the requests are created.

I'm using request-promise-native in my service and running my tests with Mocka.

Masza
  • 331
  • 1
  • 3
  • 12

2 Answers2

1

For someone who stumbles on this question, you can certainly have different responses from the same path using nock chaining.

You can try something like:

nock(apiUrl)
.matchHeader("x-auth-token", firstToken)
.get(/places/)
.reply(200, placeList1)
.matchHeader("x-auth-token", secondToken)
.get(/places/)
.reply(200, placeList2)
Sarneet Kaur
  • 2,860
  • 1
  • 14
  • 12
  • This response is clearly misleading. The actual API `matchHeader(name,value)` matches all headers on any interceptor created within a single scope. https://github.com/nock/nock/blob/20e9f8a0661cc0ca12891fea35ebce21c222d85e/tests/test_header_matching.js#L70 – ejb Nov 15 '20 at 01:11
  • 1
    It is not misleading. You probably didn't see that it can match multiple headers too. https://github.com/nock/nock/blob/20e9f8a0661cc0ca12891fea35ebce21c222d85e/tests/test_header_matching.js#L127 – Sarneet Kaur Nov 18 '20 at 18:11
  • good catch! You have to be careful about the order of the method calls though, it did not work as the answer was written. – ejb Nov 20 '20 at 13:37
  • Isn't it worth editing the answer above, @SarneetKaur, it ISN'T `.matchHeaders(` it is singular. – Marvin Sep 09 '22 at 14:45
0

Using Jest the previous answer will work as expected, but should the test fail the output will be entirely dependent on how request failures are logged within the snippet being tested.

To make the failure more explicit and the tests easier to maintain, you may consider inserting a mock function into your call to matchHeader(name, ()=>{}) so that the values can be observed as part of the test.

test('project authenticates multiple accounts', () => {
  const xAuthHeader = jest.fn(s => true);

  const scope = nock(apiUrl)
    .matchHeaders("x-auth-token", xAuthHeader)
    .get('/places/')
    .reply(200, placeList1)
    .get('/places/')
    .reply(200, placeList2);

  await myProject.authenticate()

  expect(xAuthHeader).toHaveNthReturnedWith(1,[firstToken]);
  expect(xAuthHeader).toHaveNthReturnedWith(2,[secondToken]);
});

In this manner, should the test fail, the jest framework will explicitly report the mismatched header values in the summary.

ejb
  • 614
  • 6
  • 12