Next.js 与 Vitest 结合 next-international 的国际化单元测试编写指北

May 14·2 min
AI 生成的摘要
本文介绍了如何使用 Vitest 进行 Next.js 应用的国际化单元测试。首先,安装 Vitest 及其依赖,并配置 vitest.config.ts 文件。接着,在项目根目录创建 vitestSetup.ts 文件,模拟 useRouter 方法以提供国际化数据。然后,编写单元测试文件 demo.test.tsx,使用 next-international 创建 I18nProvider 并渲染组件进行测试。最后,通过运行 pnpm run test 命令执行单元测试。

next-international 简介

next-international 是 Next.js 的众多国际化框架之一,因其 100% 类型安全和简单配置而受到青睐。本文不涉及 next-international 的配置,如需了解,请参考官方文档

安装与配置

1. 安装Vitest

安装 Vitest 及其依赖:

pnpm install -D vitest @vitejs/plugin-react jsdom @testing-library/react

在项目根目录创建 vitest.config.ts 文件,并添加以下配置:

vitest.config.ts
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./vitestSetup.ts']
  }
})

更新 package.json 文件,添加测试命令:

package.json
{
  "scripts": {
    "test": "vitest"
  }
}

在 tsconfig.json 文件中添加类型定义:

tsconfig.json
{
  "compilerOptions": {
    "types": ["@testing-library/jest-dom"]
  }
}

2. 配置Vitest

在项目根目录创建 vitestSetup.ts 文件,并添加以下内容:

import type { NextRouter } from 'next/router'
import * as nextRouter from 'next/router'
// 在 Next.js 应用外部直接使用 useRouter 会触发 "NextRouter was not mounted" 错误。
// 为了解决这个问题,我们通过模拟(mock)来劫持 useRouter 方法,并提供必要的国际化数据。
import { beforeEach, vi } from 'vitest'
import '@testing-library/jest-dom'
beforeEach(() => {
  // eslint-disable-next-line @typescript-eslint/no-var-requires
  vi.spyOn(nextRouter, 'useRouter').mockImplementationOnce(
    () =>
      ({
        query: 'Mock_Vitest',
        locale: 'en',
        defaultLocale: 'en',
        locales: ['en']
      }) as unknown as NextRouter
  )
})

afterEach(() => {
  vi.clearAllMocks()
})

3. 编写单元测试文件

在项目根目录的 test 文件夹下创建 demo.test.tsx 文件,并添加以下内容:

demo.test.tsx
import { createI18n } from 'next-international'
import { describe, it } from 'vitest'
import en from '../locales/messages/enUS'
import { render, screen, waitFor } from './customRender'

describe('Example test', () => {
  it('just an example', async () => {
    const { useI18n, I18nProvider } = createI18n({
      en: () => import('../locales/messages/enUS'),
    })

    function App() {
      const t = useI18n()

      return <p>{t('Hello')}</p>
    }

    render(
      <I18nProvider locale={en}>
        <App />
      </I18nProvider>
    )

    await waitFor(() => {
      expect(screen.getByText('Hello')).toBeInTheDocument()
    })
  })
})

4. 进行单元测试

在终端运行以下命令以执行单元测试:

pnpm run test

完成以上步骤后,即可实现基于国际化的单元测试。

最后修改时间: Aug 30
cd ..