Skip to content

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

🕒 发布时间: 🕒 阅读时间: 0 分钟✍︎ 文章字数: 0

前言

Vitest 简介

虽然 Next.js 并不是使用 Vite 构建的项目,但 Vitest 依然可以在 Next.js 中使用。它兼容 Jest 的语法,提供良好的开发者体验。

next-international 简介

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

安装与配置

1. 安装Vitest

安装 Vitest 及其依赖:

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

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

typescript
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";

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

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

JSON
{
    "scripts": {
    "test": "vitest"
  },
}

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

JSON
{
  "compilerOptions":{
    "types": ["@testing-library/jest-dom"],
  }
}

2. 配置Vitest

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

typescript
  // 在 Next.js 应用外部直接使用 useRouter 会触发 "NextRouter was not mounted" 错误。
  // 为了解决这个问题,我们通过模拟(mock)来劫持 useRouter 方法,并提供必要的国际化数据。
import { beforeEach, vi } from "vitest";
import "@testing-library/jest-dom";
import * as nextRouter from "next/router";
import type { NextRouter } from "next/router";
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 文件,并添加以下内容:

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


 
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. 进行单元测试

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

bash
pnpm run test

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

Last updated: