Expo Router的测试配置

编辑

了解如何在使用Expo Router时为你的应用创建集成测试。


Expo Router 依赖于你的文件系统,这在为集成测试设置模拟时可能会带来挑战。Expo Router 的子模块expo-router/testing-library是一个基于流行的@testing-library/react-native构建的测试工具集,可以让你快速创建预配置为测试的内存中的Expo Router应用。

配置

在继续之前,请确保根据使用 Jest 进行单元测试@testing-library/react-native在你的项目中设置了jest-expo

注意:使用 Expo Router 时,请勿将测试文件放在 app 目录中。所有 app 目录中的文件必须是路由或布局文件。相反,请使用 __tests__ 目录或单独的目录。此方法在使用 Jest 进行单元测试中进行了说明。

renderRouter

renderRouter扩展了render的功能,以简化使用Expo Router的测试。它返回与render相同的查询对象,并与screen兼容,允许你使用标准的查询API来定位组件。

renderRouter接受与render相同的选项,并引入了一个额外的选项initialUrl,用于设置深度链接的初始路由。

内联文件系统

renderRouter(mock: Record<string, ReactComponent>, options: RenderOptions)

renderRouter可以通过将对象作为第一个参数传递给此函数来提供文件系统的内联模拟。对象的键是模拟的文件系统路径。定义这些路径时不要使用前导相对(./)或绝对(/)表示法,并排除文件扩展名。

app.test.tsx
import { renderRouter, screen } from 'expo-router/testing-library'; it('my-test', async () => { const MockComponent = jest.fn(() => <View />); renderRouter( { index: MockComponent, 'directory/a': MockComponent, '(group)/b': MockComponent, }, { initialUrl: '/directory/a', } ); expect(screen).toHavePathname('/directory/a'); });

使用`null`组件的内联文件系统

renderRouter(mock: string[], options: RenderOptions)

renderRouter提供一个字符串数组将创建一个内联模拟文件系统,其中包含null组件({ default: () => null })。这对于测试不需要测试路由输出的场景非常有用。

app.test.tsx
import { renderRouter, screen } from 'expo-router/testing-library'; it('my-test', async () => { renderRouter(['index', 'directory/a', '(group)/b'], { initialUrl: '/directory/a', }); expect(screen).toHavePathname('/directory/a'); });

高速缓存路径

renderRouter(fixturePath: string, options: RenderOptions)

renderRouter可以接受一个目录路径以模拟现有的高速缓存。确保提供的路径相对于当前测试文件。

app.test.js
it('my-test', async () => { const MockComponent = jest.fn(() => <View />); renderRouter('./my-test-fixture'); });

带覆盖的高速缓存路径

renderRouter({ appDir: string, overrides: Record<string, ReactComponent>}, options: RenderOptions)

对于更复杂的测试场景,renderRouter可以同时利用目录路径和内联模拟方法。appDir参数接受一个表示目录路径的字符串。覆盖参数是一个内联模拟,可用于覆盖appDir中的特定路径。此组合允许对模拟环境进行精细控制。

app.test.js
it('my-test', async () => { const MockAuthLayout = jest.fn(() => <View />); renderRouter({ appDir: './my-test-fixture', overrides: { 'directory/(auth)/_layout': MockAuthLayout, }, }); });

Jest 匹配器

以下匹配器已添加到expect中,可以用于断言screen上的值。

toHavePathname()

断言当前路径名与给定字符串匹配。该匹配器使用当前screen上的usePathname钩子的值。

app.test.ts
expect(screen).toHavePathname('/my-router');

toHavePathnameWithParams()

断言当前路径名(包括URL参数)与给定字符串匹配。这对于断言URL在网页浏览器中的出现很有用。

app.test.ts
expect(screen).toHavePathnameWithParams('/my-router?hello=world');

toHaveSegments()

断言当前片段与字符串数组匹配。该匹配器使用当前screen上的useSegments钩子的值。

app.test.ts
expect(screen).toHaveSegments(['[id]']);

useLocalSearchParams()

断言当前本地URL参数与对象匹配。该匹配器使用当前screen上的useLocalSearchParams钩子的值。

app.test.ts
expect(screen).useLocalSearchParams({ first: 'abc' });

useGlobalSearchParams()

断言当前屏幕的路径名与某个值匹配。使用useGlobalSearchParams钩子的值进行比较。

断言当前全局URL参数与对象匹配。该匹配器使用当前screen上的useGlobalSearchParams钩子的值。

app.test.ts
expect(screen).useGlobalSearchParams({ first: 'abc' });

toHaveRouterState()

一个先进的匹配器,断言当前路由器状态与对象匹配。

app.test.ts
expect(screen).toHaveRouterState({ routes: [{ name: 'index', path: '/' }], });