typescript - 如何模拟 ServiceBusError 异常以进行 Jest 测试?

标签 typescript unit-testing jestjs mocking azureservicebus

我有一个像这样的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 手动模拟,以便

  1. ServiceBusClient 导入导入模拟版本而不是真实版本

  2. 模拟版本的 createSender 方法返回模拟发送者。

  3. 模拟发送者的 sendMessages 方法在测试中执行您希望它执行的任何操作(例如抛出特定异常)。您可以通过在测试调用正在测试的代码之前配置模拟来实现这一点。

以下是一些特定于 Jest 和 Typescript 的资源,可以为您提供帮助:

问题更新的答案更新

您想要做的是能够根据每个测试用例的需要更改模拟 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/

相关文章:

javascript - 如何用 Jest stub 类的所有方法?

javascript - typescript :上下文保存。这样做是个好主意吗?

angular - Karma 使用内置管道的自定义管道测试 Angular X (5) 组件

angular - 如何使模态在 Ionic2 中变为全屏?

apache-flex - 柔性,柔性单元 : How to test that an event is dispatched twice?

javascript - 实习生 - 调试内存不足异常

reactjs - React-Boilerplate 默认测试抛出 TypeError : Cannot read property 'store' of null

javascript - 如何将非数字字符串转换为 int

asp.net-mvc - 我可以在 'unit testing' 时使用断点(如调试时)吗?

javascript - 如何在类星体测试中运行单文件测试