skip to content

In a React Native Jest suite, how do you wire the mocks that AsyncStorage, NetInfo and Reanimated ship instead of writing your own?

level: middleimportance: should knowfreq 42%

answer

  1. check the library's own Jest guide
  2. AsyncStorage: in-memory store at /jest
  3. NetInfo: jest/netinfo-mock.js, cellular by default
  4. Reanimated: resolver plus setUpTests()
  5. reset shared state between tests

basics

~10 s

Each library ships its own Jest integration: AsyncStorage's in-memory mock at @react-native-async-storage/async-storage/jest, NetInfo's jest/netinfo-mock.js, and Reanimated's Jest resolver plus setUpTests() in a setup file.

solid answer

~30 s

Libraries with native parts usually ship a Jest mock that tracks their API, so prefer it over a hand-written one. AsyncStorage 3 exports an in-memory implementation from `@react-native-async-storage/async-storage/jest`: point a `__mocks__/@react-native-async-storage/async-storage.js` file or an inline `jest.mock` at it, and reset stored data between tests. NetInfo ships `@react-native-community/netinfo/jest/netinfo-mock.js`, whose `fetch` and `useNetInfo` report a connected cellular state until you override them for an offline test. Reanimated 4 asks for `resolver: 'react-native-reanimated/jest/resolver'` in the Jest config and `require('react-native-reanimated').setUpTests()` in a `setupFilesAfterEnv` file, which adds `toHaveAnimatedStyle` and lets fake timers drive animations.

code

javascript · 17 lines
javascript
// jest.config.js
module.exports = {
  preset: '@react-native/jest-preset',
  resolver: 'react-native-reanimated/jest/resolver',
  setupFiles: ['<rootDir>/jest.setup.js'],
  setupFilesAfterEnv: ['<rootDir>/jest.after-env.js'],
};

// jest.setup.js
import mockRNCNetInfo from '@react-native-community/netinfo/jest/netinfo-mock.js';
jest.mock('@react-native-community/netinfo', () => mockRNCNetInfo);

// jest.after-env.js
require('react-native-reanimated').setUpTests();

// __mocks__/@react-native-async-storage/async-storage.js
module.exports = require('@react-native-async-storage/async-storage/jest');

go deeper

for a junior

Recall that libraries with native code ship Jest mocks and that you wire them through jest.mock, a mocks file or a setup file.

for a middle

Explain how AsyncStorage's in-memory mock, NetInfo's jest.fn mock and Reanimated's resolver plus setUpTests differ, and which defaults each assumes.

for a senior

Catch the traps: state that persists between tests, an online default hiding offline branches, and a Reanimated setup that silently runs native code paths.

for a principal

Prefer shipped mocks for upgrade resilience but wrap libraries you depend on heavily, so tests pin your contract rather than a vendor's mock.

## Why library-shipped mocks come first A library with a native module cannot run under Jest, because Node has no native binary. You can write a `jest.mock` factory yourself, but a mock the library **ships** has two advantages: it matches the library's current API, and it moves with the library when you upgrade. The first place to look is the library's own testing or Jest guide. The three libraries interviewers most often name each take a different shape. ## AsyncStorage 3: a working in-memory store `@react-native-async-storage/async-storage` exports a mock at the subpath **`/jest`**. It is not a set of empty stubs: it is a **full in-memory implementation** of the AsyncStorage interface (`getItem`, `setItem`, `removeItem`, `getMany`, `setMany`, `removeMany`, `getAllKeys`, `clear`) backed by a `Map`. Two ways to install it: 1. Create `__mocks__/@react-native-async-storage/async-storage.js` next to `node_modules` containing `module.exports = require('@react-native-async-storage/async-storage/jest');`. Jest picks it up automatically for every test. 2. Call `jest.mock('@react-native-async-storage/async-storage', () => require('@react-native-async-storage/async-storage/jest'))` at the top of one test file. Because the store is real, data written in one test is still there in the next test of the same file. The mock also exports `clearAllMockStorages`, which its guide describes as clearing all in-memory storages. In 3.1.1's source it empties the registry that `createAsyncStorage` reads from; an instance a module already holds, including the default export, keeps its own map. So `await AsyncStorage.clear()` (or `clear()` on each instance your code holds) in `beforeEach` is the reliable reset. The library's Jest guide also notes that the package ships as ES module source, so it must be allowed through the transform step. ## NetInfo: preset answers you override `@react-native-community/netinfo` ships **`jest/netinfo-mock.js`**. Its README recommends registering it in a setup file: ```js import mockRNCNetInfo from '@react-native-community/netinfo/jest/netinfo-mock.js'; jest.mock('@react-native-community/netinfo', () => mockRNCNetInfo); ``` Every function is a `jest.fn()`. `fetch` and `refresh` resolve, and `useNetInfo` returns, a default state: `type: 'cellular'`, `isConnected: true`, `isInternetReachable: true`. `addEventListener` returns an unsubscribe function. So an app under test is **online by default**; an offline banner test must override the hook, for example `jest.mocked(useNetInfo).mockReturnValue({ ...state, isConnected: false })`. ## Reanimated 4: a resolver and a setup call Reanimated 4 does not ship a single module mock. Its Jest guide asks for two changes: - in `jest.config.js`, `resolver: 'react-native-reanimated/jest/resolver'`, which makes Jest resolve Reanimated's and React Native Worklets' web implementations instead of the native ones; - in a `setupFilesAfterEnv` file, `require('react-native-reanimated').setUpTests()`, which takes an optional config whose default is `{ fps: 60 }` and registers the matchers `toHaveAnimatedStyle` and `toHaveAnimatedProps`. The guide tells you to follow React Native Worklets' Jest guide first, since Reanimated 4's worklets live in that package. With this in place, `jest.useFakeTimers()` plus `jest.advanceTimersByTime(250)` moves an animation to its 250 ms point, and `toHaveAnimatedStyle` checks the style there. ## Side by side | Library | What you add | What the double does | Reset between tests | |---|---|---|---| | AsyncStorage 3 | `__mocks__` file or `jest.mock` pointing at `/jest` | Real in-memory storage | `await AsyncStorage.clear()` on each held instance | | NetInfo 12 | `jest.mock` with `jest/netinfo-mock.js` | `jest.fn()`s returning a connected cellular state | Re-set return values; clear mocks | | Reanimated 4 | Jest `resolver` plus `setUpTests()` | Web implementation driven by timers | Fake timers per test | ## Where each piece of wiring lives 1. **`__mocks__` directory** next to `node_modules`: automatic for every suite, good for AsyncStorage. 2. **`setupFiles`**: runs before the test framework loads, good for `jest.mock` calls such as NetInfo's that every suite needs. 3. **`setupFilesAfterEnv`**: runs after the framework is installed, required for anything that calls `expect.extend`, such as Reanimated's `setUpTests()`. 4. **Inside one test file**: for a mock that only that suite needs, or a suite that must override a global default. ## When to write your own anyway - The library ships no mock, or its mock lacks a method you call. - You want the test to depend on **your** wrapper, not the library's API, in which case you mock the wrapper instead. - The shipped mock's defaults hide a branch you need, such as NetInfo's online default hiding offline handling. The interview point is judgment: know that the mocks exist, how each is wired, and what default each one quietly assumes.

  • An offline-banner test passes even though the banner never renders; what is wrong with the NetInfo setup?
    NetInfo's shipped mock reports `isConnected: true` on cellular by default, so a test that never overrides `useNetInfo` or `fetch` exercises only the online branch. Override the return value in the offline test and assert the banner appears, and add an online test that asserts it does not.
  • Why can two AsyncStorage tests in the same file affect each other?
    The shipped mock is a real in-memory store, not a stub, so a value set in one test is still there in the next. Call `await AsyncStorage.clear()` in `beforeEach`. In 3.1.1's source, `clearAllMockStorages` only empties the registry `createAsyncStorage` reads from, so an instance already imported keeps its data unless you clear it directly.

saying these in an interview costs you the question

  • AsyncStorage's Jest mock is a set of empty jest.fn stubs
  • NetInfo's mock reports the device offline unless configured
  • Reanimated 4 is mocked with a single jest.mock line and nothing else
  • Library mocks reset their state automatically between tests
  • Hand-written mocks are always safer than a library's shipped mock