【问题标题】:how to unit test if handler function is called when using middy使用 middy 时如何对处理函数进行单元测试
【发布时间】:2022-01-09 20:07:02
【问题描述】:

我在 middy 中使用 http 请求函数作为处理函数,然后在发起 http 请求之前使用 ssm 中间件获取一些 ssm 参数。 像这样:

  const makeThirdPartyServiceRequest = middy(async ({ params }) => {
  logger.info(`SENDING Request to ${endpoint} API`)
  const url = `https://someurltoathirdpartyservice`
  const options = {
    method: 'POST',
    body: params
  }

  return helpers.makeRequest(url, options)
})
makeThirdPartyServiceRequest.use(ssm(......))

然而,在我开玩笑的单元测试中,我试图模拟 makeThirdPartyServiceRequest 并明确表示它应该解析为一个值:

jest.mock('../src/thirdPartyService', () => ({
  __esModule: true,
  default: {
    ...(jest.requireActual('../src/thirdPartyService') as { default: {} }).default,
    makeThirdPartyServiceRequest: jest.fn()
  }
}))
export {}
import thirdPartyService from '../src/thirdPartyService'

然后在测试中我说:

describe('makeThirdPartyServiceRequest()', () => {
  it('should makeThirdPartyServiceRequest', async () => {
    // Given

    // })
    const mockedThirdPartyServiceRequest = mocked(thirdPartyService.makeThirdPartyServiceRequest).mockResolvedValue({})
    // When
    const result = await thirdPartyService.makeThirdPartyServiceRequest(something)
    // Then
    expect(mockedThirdPartyServiceRequest).toHaveBeenCalledTimes(1)
    expect(mockedThirdPartyServiceRequest.mock.calls[0][0].params.toString()).toBe(expectedParams)
  })
})

但是由于某种原因,middy 中间件仍在被调用,这显然是我不想要的,我试图嘲笑......我做错了什么?

【问题讨论】:

  • @middy 中的每个包都有许多示例,说明如何在 __tests__ 文件夹 (github.com/middyjs/middy/tree/main/packages) 中执行此操作。在 v2.x 中切换到 ava 之前,middy 的 v1.x 使用了 jest

标签: javascript node.js aws-lambda jestjs middy


【解决方案1】:

你需要模拟middy,让它变成一个无用的函数。该函数将函数作为参数并返回该参数。

import thirdPartyService from '../src/thirdPartyService'

jest.mock('@middy/core', () => {
  return (handler) => {
    return {
      use: jest.fn().mockReturnValue(handler), // ...use(ssm()) will return handler function
    }
  }
})

describe('thirdPartyService()', () => {
  beforeEach(() => {
    jest.spyOn(helpers, 'makeRequest') // spy on helpers unit
  })

  describe('makeThirdPartyServiceRequest', () => {
    it('should make a request with correct parameters', async () => {
      // Given
      const url = `https://someurltoathirdpartyservice`
      const params = 'any params'
      const apiResponse = 'any response'
      mocked(helpers.makeRequest).mockResolvedValue(apiResponse)

      // When
      const actual = await thirdPartyService.makeThirdPartyServiceRequest(params)

      // Then
      expect(actual).toBe(apiResponse)
      expect(helpers.makeRequest).toHaveBeenCalledWith(
        url,
        {
          method: 'POST',
          body: params
        }
      )
    })
  })
})

【讨论】:

  • 非常感谢您的回复!我按照您的示例进行操作,但是由于我也使用了 before 函数,因此我收到一个错误,即 before 函数不是函数: TypeError: (0 , core_1.default)(...).use(...).before 是不是函数
  • 再次感谢,这将我引向正确的方向,因此将其标记为有效答案!
【解决方案2】:

hoangdv 回答也是有效的,但我会继续回答。

如果你完全想模拟 middy,你可以模拟如下:

    jest.mock('@middy/core', () => {
      return (handler) => {
        return {
          use: jest.fn().mockImplementation(() => {
            // ...use(ssm()) will return handler function
            return {
              before: jest.fn().mockReturnValue(handler)
            }
          })
        }
      }
    })

但是,如果您不想完全模拟 middy,则可以改为模拟之前调用的 middy/util 中的异步 getInternal 函数,如下所示:

    jest.doMock('@middy/util', () => ({
      ...(jest.requireActual('@middy/util') as {}),
      getInternal: jest.fn()
    }))
import { getInternal } from '@middy/util'

然后在测试中

    describe('thirdPartyService()', () => {
      beforeEach(() => {
        jest.spyOn(helpers, 'makeRequest') // spy on helpers unit
      })
    
      describe('makeThirdPartyServiceRequest', () => {
        it('should make a request with correct parameters', async () => {
          // Given
          const url = `https://someurltoathirdpartyservice`
          const params = 'any params'
          const apiResponse = 'any response'
          mocked(getInternal).mockResolvedValue({
          twilioSecrets: { accountSid: 'someSID', serviceId: 
          'someServiceID', token: 'someToken' }
          })
          mocked(helpers.makeRequest).mockResolvedValue(apiResponse)
    
          // When
          const actual = await thirdPartyService.makeThirdPartyServiceRequest(params)
    
          // Then
          expect(actual).toBe(apiResponse)
          expect(helpers.makeRequest).toHaveBeenCalledWith(
            url,
            {
              method: 'POST',
              body: params
            }
          )
        })
      })
    })

这将模拟 middy 的异步部分。

【讨论】:

    猜你喜欢
    • 2021-07-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多