我使用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)
我的期望是,在测试中
相反,发生的是,当我提供“错误的用户名”时,nock会使用我提供的数据返回200,即,它与我提供的用户名中第一个不匹配。
这表明,我根本无法检查用户名。显然我做错了,有些事情我不理解。那就是我所追求的:)
好吧,我现在明白了这个问题。不幸的是,我认为如果不查看实际的测试代码就无法真正回答该问题。通常,当nock
ing不能按预期工作时,我发现要找出问题所在是困难且令人沮丧的。对我而言,最有效的方法是使各自的特征nock
或多或少地以较小的幅度递增,并查看何时发生更改(然后大部分时间我意识到我忘了解释某件事...)。
因此,在您的情况下,我将尝试删除.persist
,然后尝试对200- nock
进行注释,以查看另一个是否匹配,依此类推。
TL; DR:尝试删除内容,直到发生更改以找出问题为止。
让我以不确定我是否正确理解您的问题为开头回答这个问题。希望我能分享一些能帮助您的见解。
我不想编写测试来检查sdk是否完成其工作,我们都知道它是:)
谢谢你的客气话!确实,我认为大多数人都同意您不必测试依赖项是否有效。话虽如此,我发现最有效的方法是将您对依赖项的调用(在本例中为SDK)隔离到某个地方,然后在测试中模拟您的隔离。例如,如果将对销售订单服务的调用放在一个函数中getSalesOrders
,则可以使用类似的方法jest.spyOn
来声明该函数应在给定测试中返回的数据,而不必处理任何与HTTP相关的问题。另外,如果您不喜欢在运行时覆盖内容,则可以通过依赖项注入实现相同的目的。无论哪种方式,都存在有关代码组织被入侵的大量讨论,因此请稍加注意。
在nock中包括授权标头时,我个人更喜欢您展示的第二种方法(即reqheaders: { authorization: valueThatIExpectInThisTest }
),因为这最清楚地传达了您的假设以及相应的响应。
最后,我看到您.persist()
在所有示例中都使用了。这是故意的吗?默认情况下,nock
仅匹配一次模拟。最初来自Java和WireMock,这种方法一开始就欺骗了我,但我开始偏爱它,因为它可以更好地控制并防止意外匹配的内容。最后,我仍然会nock.cleanAll()
在每次测试后打电话给我,但这只是“安全胜过遗憾”。
希望这对您有所帮助!如果没有,请随时提出其他问题!
嗨,丹尼斯,谢谢您的回答。对于测试策略,我完全同意。因此,我试图解释一下,实际上,可以说分别激活每个测试中的模拟是一种更好的方法,也可以解决我的问题。我问这个问题来理解一个错误(很可能是从我这边来看):为什么nock匹配第一个函数,尽管我提供了错误的用户名,但第一个函数却带有“ CorrectBackendDetails”。我希望它可以匹配第二个而不是第一个。这里出了点问题,我无法弄清楚。那就是我所追求的一切。
因此,我对问题进行了编辑,使其更加清晰。如果您需要更多信息,更多说明等,请告诉我。
我更新了答案,希望能有所帮助。
我在这里犯了一个愚蠢的错误,丹尼斯让我意识到了。因此,对于那些来这里寻求答案的人,我问题中的第二个代码块可以正常工作。您可以使用“ reqheaders”来匹配用户名和密码。我将此答案标记为正确,因为此处的讨论富有成果。