我使用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
函数(上面的代码)来获取数据。现在,我为同一端点创建模拟;一次使用“正确的用户名”,另一次使用“错误的用户名”,并将两者都保留(上面的第二个代码块,其中一个带有reqheader)
我的期望是,在测试中
发生的事情是,当我提供“错误的用户名”时,nock会使用我提供的数据返回200,即它与我提供的用户名中第一个不匹配。
这表明,我根本无法检查用户名。显然我做错了,有些事情我不理解。那就是我所追求的:)
答案 0 :(得分:0)
好的,我现在明白了这个问题。不幸的是,我认为如果没有看到实际的测试代码就不可能真正回答这个问题。通常,当nock
不能按预期工作时,我很难找出问题所在,感到沮丧。对我来说,最有效的方法是使各自的nock
或多或少地以较小的增量具体化,并查看什么时候发生了变化(然后大部分时间我意识到我忘了考虑某些事情了……)
因此,在您的情况下,我将尝试删除.persist
,然后尝试对200-nock
进行注释,以查看另一个匹配的对象,依此类推。
TL; DR::尝试删除内容,直到发生更改为止,以找出问题所在。
让我以不确定我是否正确理解您的问题为开头作答。希望我能分享一些能帮助您的见解。
我不想编写测试来检查sdk是否完成了工作,我们都知道它可以:)
谢谢您的客气话!确实,我认为大多数人都同意您不必测试依赖项是否有效。话虽如此,我发现最有效的方法是将您对依赖项的调用(在本例中为SDK)隔离到某个地方,然后在测试中模拟您的隔离。例如,如果将对销售订单服务的调用放在函数getSalesOrders
中,则可以使用类似jest.spyOn
的方法声明函数在给定测试中应返回哪些数据,而不必处理任何与HTTP相关的内容。
另外,如果您不喜欢在运行时覆盖内容,则可以通过依赖项注入实现相同的目的。无论哪种方式,都存在关于代码组织被入侵的大量讨论,因此请耐心等待。
当要在nock中包括授权标头时,我个人更喜欢您展示的第二种方法(即使用reqheaders: { authorization: valueThatIExpectInThisTest }
),因为这最清楚地传达了您的假设以及相应的响应。
最后,我看到您在所有示例中都使用.persist()
。这是故意的吗?默认情况下,nock
仅匹配一次模拟。最初来自Java和WireMock,这种方法一开始就欺骗了我,但我开始偏爱它,因为它可以更好地控制并防止意外匹配的内容。最后,在每次测试后我仍然会打电话给nock.cleanAll()
,但这只是“安全胜过遗憾”。
希望这对您有帮助!如果没有,请随时提出其他问题!