Run your tests against real React Native — the same JavaScript that ships in your app — mocking only the native-module boundary. One plugin, two engines, zero config.
The native engine runs RN's real JavaScript and mocks only the thin native boundary — native modules and the host-component registry, not the View/Text component JS. Jest's preset mocks more, so the native engine has higher fidelity for accessibility, RN-API behavior, and integration, with no mock drift.
A fast mock engine, one flag away
engine "mock" is a zero-dependency pure-JS reimplementation of React Native. Reach for it when you want maximum determinism and no RN at all — pure-logic suites, environment control.
Zero config
One plugin auto-injects setup files, configures @testing-library/react-native, stubs assets, and resolves platform-specific files. No manual setupFiles, no jest-preset, no transformIgnorePatterns.
Presets for the ecosystem
Reanimated, Gesture Handler, Safe Area, Navigation, Screens, AsyncStorage, MMKV, SVG, WebView, Device Info, and Expo are auto-detected and shadowed — under both engines. Delete your manual native-lib mocks.
One runner across your codebase
Already using Vitest for web or server code? Get Vitest's watch mode, UI, and native ESM tooling for your React Native tests too. One runner, one config language.
Adopt incrementally
Point vitest-native at new tests while your existing Jest suite keeps running. A jest-compat layer clears the mechanical Jest-API coupling so you can migrate older tests as you touch them.
reactNative() with no options resolves to the native engine — real React Native JS, mocking only the native boundary — whenever your project's Babel preset is present (i.e. any real RN app). No further setup.
Jest with @react-native/jest-preset is the React Native standard and works well. Reach for vitest-native when you value:
Higher-fidelity option — Jest's RN preset and vitest-native both run real RN JS and mock the native side, but Jest mocks more (it swaps RN's core components and a few APIs for passthrough stand-ins). vitest-native's engine: 'native' mocks only the deeper native boundary, so your tests run RN's real component JS — or drop to a fast full mock when you don't need that. How the boundaries differ →
DX — Vitest's watch mode, UI, and native ESM tooling.
Unification — one runner if you also test web or server code with Vitest.
The reproducible guarantee is a CI-gated behavioral cross-check: 56 probes run the same assertions under the mock engine and real React Native across React Native 0.81–0.85, and any divergence fails the build. Anyone can run it (bun run crosscheck). On top of that, the full CI gate runs lint, typecheck, build, and the mock + native + hot suites across an OS × Node matrix.
We've also run real apps' own test suites under the native engine. react-native-paper's suite passes 625 of 734 tests (~85%) — no paper source changed, just an RNTL bump and the test config/setup. The remaining failures are tests coupled to Jest's RN-mock internals (e.g. vi.spyOn(View.prototype, 'measure'), deep jest.mock('react-native/…') of Appearance/Dimensions), not vitest-native bugs. The Expo-based obytes template runs 34 of 40 (~85%) — a more deeply-coupled case that needed a few library mocks. Both are reproducible: see vitest-native-bakeoffs. We've also migrated a Rocket.Chat suite in local testing.
Beta. Some APIs may still shift before 1.0. Maintained successor to vitest-community/vitest-react-native — same core idea, rebuilt for modern Vitest (v4).