Jest 62,362 has no Android underneath it, so every native module needs a stand-in. The presets cover React Native 36,878 and Expo 6,418 ; third-party modules are on their own. BookNest's very first test, the cart store's, failed before running a line with NativeModule: AsyncStorage 5,070 is null, because the store persists through AsyncStorage (Persisting Zustand State). Well-maintained libraries ship a mock, and a setup file installs it for every test file:
// Runs before every test file: stand-ins for native modules Jest cannot load
jest.mock('@react-native-async-storage/async-storage', () =>
require('@react-native-async-storage/async-storage/jest/async-storage-mock'));For a module without a mock, write the factory yourself and return only what your code calls, as the cart test did for the session. A jest.mock() in a test file overrides a mock for that file alone. jest-expo's expo-localization reports an American English phone, so a Spanish test replaces it; Babel 41,624 hoists the call above the imports, so src/i18n initializes with the fake locale:
jest.mock('expo-localization', () => ({
getLocales: () => [{ languageCode: 'es', languageTag: 'es-ES', textDirection: 'ltr' }],
}));
// ...
expect(i18n.t('cart.items', { count: 3 })).toBe('3 libros en tu carrito');
expect(money(24)).toBe('24,00\u00a0US$'); // a no-break space before US$The first draft expected '24,00 US$' and failed with Expected: "24,00 US$" and Received: "24,00 US$": Intl.NumberFormat puts a no-break space (U+00A0) before the currency. Remember what a mock cannot prove: this test checks the Spanish strings and formats, not that expo-localization reads the phone's settings.