温馨提示:本文翻译自stackoverflow.com,查看原文请点击:javascript - How to check authorization while mocking S/4HANA responses
javascript sap-cloud-sdk

javascript - 模拟S / 4HANA响应时如何检查授权

发布于 2020-03-31 23:46:27

我使用SAP Cloud SDK(js)从S / 4HANA获取销售订单和业务合作伙伴。在测试中,我使用nock模拟S / 4。我只想在目的地正确(即授权正确)时匹配响应。一年前,我使用axios进行调用,并且使用matchHeader函数来实现该功能,如下所示:

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.");

在我开始使用sdk之后,无论我提供的目的地(例如,使用错误的用户名)都匹配第一个,并使用提供的数据返回200。我在github中做了一些搜索,发现了类似的东西:


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.");

不幸的是,这给出了相同的结果。我正在使用以下代码来发出请求:

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

因此,我模拟了所有端点并运行了所有测试。在每个测试中仅模拟必要的终点是一种解决方案,甚至可以做得更好。我不想编写测试来检查sdk是否完成其工作,我们都知道它是:)尽管如此,我想学习在匹配过程中包括授权的方法。我该怎么办?

丹尼斯回答后编辑

因此,我意识到我应该将问题更清楚地表达出来,对此感到抱歉。我使用getSalesOrder函数(上面的代码)来获取数据。现在,我为同一端点创建模拟;一次使用“正确的用户名”,另一次使用“错误的用户名”,并将两者都保留(上面的第二个代码块,其中一个带有reqheaders)

我的期望是,在测试中

  • 当我提供“正确的用户名”时,它应与第一个用户名匹配,即应返回200和我提供的模拟数据。
  • 当我提供“错误的用户名”时,它应该与第二个匹配,即应返回401,这将导致sdk引发错误等。

相反,发生的是,当我提供“错误的用户名”时,nock会使用我提供的数据返回200,即,它与我提供的用户名中第一个不匹配。

这表明,我根本无法检查用户名。显然我做错了,有些事情我不理解。那就是我所追求的:)

查看更多

提问者
MeM
被浏览
36
Dennis H 2020-02-05 22:45

更新的答案:

好吧,我现在明白了这个问题。不幸的是,我认为如果不查看实际的测试代码就无法真正回答该问题。通常,当nocking不能按预期工作时,我发现要找出问题所在是困难且令人沮丧的。对我而言,最有效的方法是使各自的特征nock或多或少地以较小的幅度递增,并查看何时发生更改(然后大部分时间我意识到我忘了解释某件事...)。

因此,在您的情况下,我将尝试删除.persist,然后尝试对200- nock进行注释,以查看另一个是否匹配,依此类推。

TL; DR:尝试删除内容,直到发生更改以找出问题为止。


原始答案:

让我以不确定我是否正确理解您的问题为开头回答这个问题。希望我能分享一些能帮助您的见解。

我不想编写测试来检查sdk是否完成其工作,我们都知道它是:)

谢谢你的客气话!确实,我认为大多数人都同意您不必测试依赖项是否有效。话虽如此,我发现最有效的方法是将您对依赖项的调用(在本例中为SDK)隔离到某个地方,然后在测试中模拟您的隔离。例如,如果将对销售订单服务的调用放在一个函数中getSalesOrders,则可以使用类似的方法jest.spyOn来声明该函数应在给定测试中返回的数据,而不必处理任何与HTTP相关的问题。另外,如果您不喜欢在运行时覆盖内容,则可以通过依赖项注入实现相同的目的。无论哪种方式,都存在有关代码组织被入侵的大量讨论,因此请稍加注意。

在nock中包括授权标头时,我个人更喜欢您展示的第二种方法(即reqheaders: { authorization: valueThatIExpectInThisTest }),因为这最清楚地传达了您的假设以及相应的响应。

最后,我看到您.persist()在所有示例中都使用了。这是故意的吗?默认情况下,nock仅匹配一次模拟。最初来自Java和WireMock,这种方法一开始就欺骗了我,但我开始偏爱它,因为它可以更好地控制并防止意外匹配的内容。最后,我仍然会nock.cleanAll()在每次测试后打电话给我,但这只是“安全胜过遗憾”。

希望这对您有所帮助!如果没有,请随时提出其他问题!