我有一个像这样的azure函数(不是实际的函数,只是下面给出了一个表示)
import { AzureFunction, Context, HttpRequest } from '@azure/functions'
import { ServiceBusClient, isServiceBusError } from '@azure/service-bus'
const serviceBusClient = new ServiceBusClient(clientConnectionString)
const sender = serviceBusClient.createSender(topicName)
const func: AzureFunction = async function (
context: Context,
req: HttpRequest
): Promise<void> {
try {
sender.sendMessages({ body: {a:"a",b:"b",c:"c" })
}
catch (error: unknown) {
if (isServiceBusError(error)) {
message = `This is the error message ${error.message} with the reason ${error.code}`
context.log.error(`Error Message: ${message}`)
} else {
context.log.error(`Error Message: Error Encountered`)
}
}
}
如何测试catch block 中的代码是否正常工作?
具体来说,如何抛出 ServiceBusError
来测试它是否被捕获并记录了适当的错误消息?
任何人都可以指导或提供有关如何进行的提示吗?
更新
我已经有以下代码来模拟服务总线并检查错误是否为服务总线错误
。但是,我无法理解如何让这个函数来模拟“好”情况(消息发送成功)和“坏”情况(抛出 ServiceBusError
)。
jest.mock('@azure/service-bus', () => {
return {
isServiceBusError: jest.fn().mockImplementation((err: unknown) => {
if (err === ServiceBusError) {
return true
} else return false
}),
ServiceBusClient: jest.fn().mockImplementation(() => {
return {
createSender: jest.fn().mockImplementation(() => {
return {
sendMessages: mockSendMessages,
}
}),
}
}),
}
})
我测试是这样的
test('Bad case: Empty Data', async () => {
const emptyData = {}
const wrongRequest = {
query: {},
body: emptyData,
}
// Action
await func(context, wrongRequest)
expect(mockSendMessages).toHaveBeenCalledTimes(0)
})
如何使用mock
抛出错误是我感到困惑的地方(仅供引用,上面的测试用例工作得很好)。
最佳答案
使用模拟测试
您需要将 sender.sendMessages
函数替换为您可以控制的模拟版本,例如在您的测试用例中抛出异常。
使用您可以在测试代码中控制的服务、对象或函数的模拟版本来模拟任意条件、状态或错误的技术是一种行之有效的最佳实践。您可以在互联网上找到大量有关模拟测试的信息。
有关模拟的一般信息:
使用Jest Manual Mocks创建一个模拟 ServiceBusClient
本质上,您必须使用 Jest 手动模拟,以便
ServiceBusClient 导入导入模拟版本而不是真实版本
模拟版本的
createSender
方法返回模拟发送者。模拟发送者的
sendMessages
方法在测试中执行您希望它执行的任何操作(例如抛出特定异常)。您可以通过在测试调用正在测试的代码之前配置模拟来实现这一点。
以下是一些特定于 Jest 和 Typescript 的资源,可以为您提供帮助:
- Jest Manual Mocks
- Customisable manual mocks in Jest and Typescript
- Using Jest Mocks + TypeScript the Right Way
- Mocking TypeScript classes with Jest
问题更新的答案更新
您想要做的是能够根据每个测试用例的需要更改模拟 ServiceBusClient 的行为方式。您只显示了代码片段,但似乎您只有一个具有硬编码行为的全局模拟。
注意 Jest 中的做法 Manual Mock examples ,模拟 fs
有一个 __setMockFiles
方法。这允许每个测试用例为不同的测试设置不同的文件。
另一种方法是replace the mock using mockImplementation() or mockImplementationOnce() :
You can replace all of the above mocks in order to change the implementation, for a single test or all tests, by calling mockImplementation() on the existing mock.
因此,您应该能够将上述链接中的示例应用到您的案例中:
import { ServiceBusClient } from '@azure/service-bus'
jest.mock('@azure/service-bus')
describe('When SoundPlayer throws an error', () => {
// mock with behavior required for all tests withing
// this describe block
beforeAll(() => {
ServiceBusClient.mockImplementation(() => {
return {
createSender: jest.fn().mockImplementation(() => {
throw //whatever err you want to test
}),
};
});
});
it('Should throw an error when calling createSender', () => {
// your test code here
});
});
关于typescript - 如何模拟 ServiceBusError 异常以进行 Jest 测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75130320/