javascript - 你能用 Jest 只模拟外部模块的一部分吗?

标签 javascript typescript jestjs

我对 Jest 非常陌生,一般来说单元测试都很好,但我很擅长为特定的东西编写测试。

我知道你可以用这样的东西来模拟外部模块..

jest.mock('@organisation/library', () => ({
 Database: jest.fn(() => ({})),
 ....,
 ...., 
}))

如果您想使用实际的方法,您可以执行类似的操作

const database = jest.requireActual('@organization/library')

我想要做的不是模拟整个库,而是仅模拟该库中的一种方法。

这可能吗?

我可能会进一步解释一下代码。

我们有一个名为StationRepository的文件。该文件包含我们 JS 框架中的一个 Database 方法。 然后该文件调用数据库并返回一个值。

我想测试该数据库查询。

这是测试

import { DatabaseModule, Pg } from '@organisation/framework'
import { StationRepository } from './StationRepository'
import { DatabaseConfig } from '../../spec'

const DatabaseInstance = new DatabaseModule()

beforeAll(async () => {
  DatabaseInstance.add('default', new Pg('default', DatabaseConfig))
  jest.clearAllMocks()
})

afterAll(async () => {
  const database = DatabaseInstance.get()
  await database.disconnect()
})

describe('find timezone', () => {
  it('can find a timezone', async () => {
    const ids = [1, 2]
    const expected = ['Pacific/Auckland', 'Australia/Adelaide']
    const results = []
    for (const id of ids) {
      const timezone: string | null = await StationRepository.findTimezone(id)
      results.push(timezone)
    }

    expect(results).toEqual(expected)
  })
})

以及存储库中的方法

import { DatabaseFacade as Database } from '@organisation/framework'


export class StationRepository {
  /**
   * Find Timezone
   *
   * Finds the station or system timezone and returns
   *  will return station timezone
   *  if no station timezone will return system timezone
   *  if no system timezone null will be returned
   *
   * @param {number} stationId - The station id to search on
   * @param {string} db - Optional - The Database connection
   *
   * @return string | null
   */
  public static findTimezone = async (
    stationId: number,
    db?: string,
  ): Promise<string | null> => {
    const query = `
      SELECT 
        (CASE
          WHEN stations.timezone IS NOT NULL 
            THEN stations.timezone
          WHEN systems.timezone IS NOT NULL 
            THEN systems.timezone
          END 
        ) AS timezone
      FROM 
        stations
      INNER JOIN systems ON systems.id = stations.system_id
      WHERE
        stations.id = $1
      `

    const result = await Database.get(db).queryOne<StationTimezone | null>.(
      query,
      [stationId],
    )
    if (!result) {
      return null
    }

    return result.timezone
  }
}

一切似乎都正常,通过测试创建连接等等。它在实际查询 Database.get() 上失败。这是通过框架加载的。如果我模拟整个框架,一切都会崩溃。

所以本质上我想做的是让框架正常运行,并且只替换DatabaseFacade区域以拉入在测试页面上创建的DatabaseInstance

这可能吗?

最佳答案

const module = '@organisation/framework'
jest.mock(module, () => ({
    ...jest.requireActual(module), // You may or may not need this line
    DatabaseFacade: DatabaseInstance
}))

这将用 DatabaseInstance 替换导出的 DatabaseFacade

(评论中的回答,记录此问题已解决)

关于javascript - 你能用 Jest 只模拟外部模块的一部分吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65621865/

相关文章:

typescript - 为什么将 jest 升级到 29.5.0 会破坏我的模拟?

javascript - AngularJS DOM 注入(inject)

javascript - 如何在 Javascript 中读取、编辑旧数组并保存新数组?

javascript - 在 node.js 中使用 stripe 实现 ach

typescript - 我应该如何在 typescript 中进行枚举比较

java - 从rest api下载文件而不需要window.open

javascript - 在javascript(React,Jquery)应用程序上预加载图像,图像加载两次

typescript - 是否有充分的理由在 typescript 项目中将编译器选项 "declaration"设置为 true

javascript - 在 Jest 中使用 test.each 时跳过一些测试

angular - 库中的单元测试组件时生成的测试失败