Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aravind3566/react-native-in-app-updates/llms.txt

Use this file to discover all available pages before exploring further.

Testing real Play Store update flows requires your app to be published (at minimum to Internal App Sharing) with a lower version code already installed on the device. This makes iterative testing slow and impractical during development. The isMock parameter solves this by swapping in Google Play Core’s FakeAppUpdateManager, which simulates the entire update lifecycle locally — no network connection or Play Store account needed.

How mock mode works

Pass true as the second argument to checkForUpdate to enable mock mode:
checkForUpdate(UpdateFlow.FLEXIBLE, true);   // mock flexible
checkForUpdate(UpdateFlow.IMMEDIATE, true);  // mock immediate
Internally, the native module replaces the real AppUpdateManager with a FakeAppUpdateManager instance and immediately sets its availability to UpdateAvailability.UPDATE_AVAILABLE. This means an update is always found in mock mode, regardless of what version is installed. The fake manager then auto-progresses through the entire update lifecycle without any real downloads or Play Store calls:
Update flowAuto-called steps
FLEXIBLEuserAcceptsUpdate()downloadStarts()downloadCompletes()
IMMEDIATEuserAcceptsUpdate()downloadStarts()downloadCompletes()installCompletes()
The native Kotlin code that drives this is shown below for reference:
// From InAppUpdatesModule.kt — FLEXIBLE path
if (isMock && manager is FakeAppUpdateManager) {
    if (manager.isConfirmationDialogVisible) {
        manager.userAcceptsUpdate()
        manager.downloadStarts()
        manager.downloadCompletes()
    }
}

// From InAppUpdatesModule.kt — IMMEDIATE path
if (isMock && manager is FakeAppUpdateManager) {
    if (manager.isImmediateFlowVisible) {
        manager.userAcceptsUpdate()
        manager.downloadStarts()
        manager.downloadCompletes()
        manager.installCompletes()
    }
}
Mock mode must never be enabled in a production build. Use an environment variable or a build-time flag to ensure isMock is always false in release builds. See the Environment flag pattern section below.

Mock test examples

import { checkForUpdate, UpdateFlow } from 'react-native-in-app-updates';

async function testFlexibleMock() {
  try {
    const result = await checkForUpdate(UpdateFlow.FLEXIBLE, true);
    // Simulates: userAcceptsUpdate → downloadStarts → downloadCompletes
    // FakeAppUpdateManager auto-triggers completeUpdate via InstallStatus.DOWNLOADED

    console.log('Mock flexible result:', result);
    // result === 'Flexible update started'
  } catch (e: any) {
    console.error('Mock flexible error:', e.code, e.message);
  }
}
The Promise resolves with "Flexible update started" once the fake flow begins. The FakeAppUpdateManager cycles through all install states synchronously, so the entire simulated download-and-install happens immediately.

Complete test component

The example below mirrors the pattern used in the library’s own example app (example/src/App.tsx) and shows how to expose both real and mock flows side-by-side during development:
import { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { checkForUpdate, UpdateFlow } from 'react-native-in-app-updates';

const IS_MOCK = __DEV__; // Only mock in development builds

export function UpdateTester() {
  const [status, setStatus] = useState('Idle');

  async function run(flow: UpdateFlow, mock: boolean) {
    setStatus(`Running ${mock ? 'mock' : 'real'} ${flow}...`);
    try {
      const result = await checkForUpdate(flow, mock);
      setStatus(`✅ ${result}`);
    } catch (e: any) {
      setStatus(`❌ [${e.code}] ${e.message}`);
    }
  }

  return (
    <View>
      <Text>{status}</Text>

      {/* Real flows — require a published Play Store version */}
      <Button title="Real Flexible"   onPress={() => run(UpdateFlow.FLEXIBLE,  false)} />
      <Button title="Real Immediate"  onPress={() => run(UpdateFlow.IMMEDIATE, false)} />

      {/* Mock flows — work entirely offline in development */}
      {IS_MOCK && (
        <>
          <Button title="Mock Flexible"  onPress={() => run(UpdateFlow.FLEXIBLE,  true)} />
          <Button title="Mock Immediate" onPress={() => run(UpdateFlow.IMMEDIATE, true)} />
        </>
      )}
    </View>
  );
}

Guarding mock mode in production

Never ship isMock: true to end users. The safest approach is to tie the flag to a build-time or environment constant:
// __DEV__ is true in Metro dev builds, false in production bundles
const result = await checkForUpdate(UpdateFlow.FLEXIBLE, __DEV__);
Because FakeAppUpdateManager always reports an update as available, mock mode is also useful for verifying your UI handles the "No update available" resolved path — simply pass isMock: false against a development build where the installed version matches the Play Store version.

What mock mode does not test

Mock mode simulates the JavaScript and native wiring faithfully, but a few things can only be verified against a real Play Store connection:
  • Whether the Play Store server actually has a newer version available.
  • Network-related failures (UPDATE_CHECK_FAILED).
  • The visual appearance of the real Play Store update UI overlays.
  • Device-specific behaviour around the immediate update blocking UI.
For end-to-end validation, publish a lower version code to Internal App Sharing and test with isMock: false.

Build docs developers (and LLMs) love