简体   繁体   中英

How to check authorization while mocking S/4HANA responses

I use SAP Cloud SDK (js) to fetch sales orders and business partners from S/4HANA. In tests, I use nock to mock the S/4. I want to match the response only if the destination is correct, ie, authorization is correct. Year ago I was using axios to make the call, and I was using matchHeader function to achieve that, something like this:

nock('https://my123456-api.s4hana.ondemand.com') // ensures the correct url
    .persist()
    .matchHeader('Authorization', 'Basic dXNlck5hbWU6dXNlclBhc3N3b3Jk') // ensures the correct technical user details
    .get(/sap\/opu\/odata\/sap\/API_SALES_ORDER_SRV\/A_SalesOrder(.*)correctSalesOrderId(.*)/) // ensures the correct id
    .reply(200, salesOrder);

nock('https://my123456-api.s4hana.ondemand.com')
    .persist()
    .matchHeader('Authorization', 'Basic d3JvbmdVc2VyTmFtZTp1c2VyUGFzc3dvcmQ=') // ensures the wrong user name
    .get(/(.*)/)
    .reply(401, "Wrong credentials etc.");

After I started using the sdk, whatever destination I provide (eg, with wrong username) matches the first one and returns 200 with the data provided. I have done a little search in the github and found something like that:


function basicCredentials(credentials) {
    return `Basic ${Buffer.from(`${credentials.username}:${credentials.password}`, 'ascii').toString('base64')}`;
}

nock('https://my123456-api.s4hana.ondemand.com', {
    reqheaders: {
        authorization: basicCredentials(givenCorrectBackendDetails())
    }
})
    .persist()
    .get(/sap\/opu\/odata\/sap\/API_SALES_ORDER_SRV\/A_SalesOrder(.*)correctSalesOrderId(.*)/) // ensures the correct id
    .reply(200, salesOrder);

nock('https://my123456-api.s4hana.ondemand.com', {
    reqheaders: {
        authorization: basicCredentials(givenWrongUserName())
    }
})
    .persist()
    .get(/(.*)/) // captures everything
    .reply(401, "Wrong credentials etc.");

Unfortunately this is giving the same result. I am using following code to make the request:

function getSalesOrder(Id, backendDetails) {
    return SalesOrder.requestBuilder()
        .getByKey(Id)
        .execute(backendDetails)
        .catch(function (error) {
            console.error(error);
            return null;
        });
}

So I mock all the endpoints and run all my tests. Mocking only necessary end point in each and every test is a solution, and could be even better. I dont want to write test to check if sdk does its job, we all know it does :) Nonetheless, I would like to learn the way to include the authorization in the matching process. What shall I do?

Edit after Dennis' answer

So I realized that I should have ask the question a bit more clear, sorry for the confusion. I use the getSalesOrder function (code above) to fetch data. Now I create mocks for the same endpoint; once with 'correct username' and other one is with 'wrong username' and persist them both (second code block above, the one with the reqheaders)

My expectation is that, in the test

  • when I provide 'correct username' it should match the first one, ie, should return me 200 and mock data I provided.
  • when I provide 'wrong username' it should match the second one, ie, should return 401, which then will cause sdk to throw an error etc.

What happens instead is, when I provide 'wrong username', nock returns 200 with the data I provided, ie, it matches the first one no mather the username I provide.

This indicates that, I am not able to check the username at all. Obviously I do a mistake, there is something I do not understand. Thats what I am after :)

Updated answer:

Okay I understand the issue now. Unfortunately, I think it's not possible to really answer that question without seeing the actual test code. Generally, when nock ing doesn't work as expected, I find it to be difficult and frustrating to find out what the issue is. What has worked best for me is to make the respective nock more or less specific in small increments and to see when something changes (and then most of the I time I realize that I forgot to account for something...).

So in your case, what I would try is removing .persist , then try commenting the 200- nock to see whether the other one then matches, and so on.

TL;DR: Try removing stuff until something changes to isolate the issue.


Original answer:

Let me preface this answer by saying that I'm not sure whether I understood your question correctly. Hopefully I can share some insights that help you nonetheless.

I dont want to write test to check if sdk does its job, we all know it does :)

Thank you for the kind words! Indeed, I think most people agree that you shouldn't have to test whether your dependencies work or not. That being said, what I found works best is isolating your calls to dependencies (in this case the SDK) somewhere and to then mock your isolation in your test. For example, if you put the calls to the sales order service in a function getSalesOrders , you could then use something like jest.spyOn to declare what data your function should return in the given test without having to deal with anything HTTP related. Alternatively, if you don't like overwriting stuff at runtime, you can achieve the same with dependency injection. Either way, there's some amount of discussion about code organization invovled, so take this with a grain of salt.

When it comes to including authorization headers in nock, I personally prefer the second approach you showed (ie with reqheaders: { authorization: valueThatIExpectInThisTest } ), as this most clearly communicates what your assumptions are and what the corresponding response should be.

Finally, I see that you use .persist() in all your examples. Is this in purpose? By default, nock only matches a mock once. Coming from Java and WireMock myself, this kind of tricked me in the beginning, but I came around to preferring it, since it gives you better control and prevents that stuff matches accidentally that shouldn't match. At the end of that I still call nock.cleanAll() after every test, but that's just "better safe than sorry".

Hope this helps you! If not, please don't hesitate to ask further questions!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM