react-native-mmkv icon indicating copy to clipboard operation
react-native-mmkv copied to clipboard

Jest tests broken with v4

Open wongk opened this issue 2 months ago • 8 comments

This section of the docs is outdated: Testing with Jest or Vitest. Running unit tests with Jest (node test environment), after upgrading, leads to the following errors:

    Failed to get NitroModules: The native "NitroModules" Turbo/Native-Module could not be found.
    * Make sure react-native-nitro-modules/NitroModules is correctly autolinked (run `npx react-native config` to verify)
    * Make sure you enabled the new architecture (TurboModules) and CodeGen properly generated the "NativeNitroModules"/NitroModules specs. See https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md
    * Make sure you are using react-native 0.75.0 or higher.
    * Make sure you rebuilt the app.
    * Make sure you ran `expo prebuild`.
    * Make sure you ran `pod install` in the ios/ directory.

    

      at Object.<anonymous> (node_modules/react-native-nitro-modules/src/turbomodule/NativeNitroModules.ts:20:9)
      at Object.require (node_modules/react-native-nitro-modules/src/NitroModules.ts:2:1)
      at Object.require (node_modules/react-native-nitro-modules/src/index.ts:2:1)
      at Object.require (node_modules/react-native-mmkv/lib/createMMKV/createMMKV.js:1:1)
      at Object.require (node_modules/react-native-mmkv/lib/index.js:2:1)

Also, this no longer exists: https://github.com/mrousavy/react-native-mmkv/blob/main/example/tests/MMKV.test.ts.

wongk avatar Oct 31 '25 14:10 wongk

Guten Tag, Hans here.

[!NOTE] New features, bugfixes, updates and other improvements are all handled mostly by @mrousavy in his free time. To support @mrousavy, please consider 💖 sponsoring him on GitHub 💖. Sponsored issues will be prioritized.

maintenance-hans[bot] avatar Oct 31 '25 14:10 maintenance-hans[bot]

PRs welcome - I don't use jest so I don't know a good answer to this.

mrousavy avatar Oct 31 '25 15:10 mrousavy

Here is the mock MMKV I added to our project for unit tests:

// Mock for react-native-mmkv
// In-memory storage implementation for MMKV interface
export class MockMMKV {
  private storage: Map<string, boolean | string | number | ArrayBuffer>
  private listeners: Set<(changedKey: string) => void>

  constructor() {
    this.storage = new Map()
    this.listeners = new Set()
  }

  set(key: string, value: boolean | string | number | ArrayBuffer): void {
    this.storage.set(key, value)
    this.notifyListeners(key)
  }

  getString(key: string): string | undefined {
    const value = this.storage.get(key)
    return typeof value === "string" ? value : undefined
  }

  getNumber(key: string): number | undefined {
    const value = this.storage.get(key)
    return typeof value === "number" ? value : undefined
  }

  getBoolean(key: string): boolean | undefined {
    const value = this.storage.get(key)
    return typeof value === "boolean" ? value : undefined
  }

  getBuffer(key: string): ArrayBuffer | undefined {
    const value = this.storage.get(key)
    return value as ArrayBuffer | undefined
  }

  getAllKeys(): string[] {
    return Array.from(this.storage.keys())
  }

  recrypt(_key: string | undefined): void {
    throw new Error("Method not implemented.")
  }

  remove(key: string): boolean {
    const result = this.storage.delete(key)
    this.notifyListeners(key)
    return result
  }

  contains(key: string): boolean {
    return this.storage.has(key)
  }

  clearAll(): void {
    const keys = Array.from(this.storage.keys())
    this.storage.clear()
    keys.forEach((key) => this.notifyListeners(key))
  }

  addOnValueChangedListener(listener: (changedKey: string) => void): { remove: () => void } {
    this.listeners.add(listener)
    return {
      remove: () => {
        this.listeners.delete(listener)
      },
    }
  }

  private notifyListeners(key: string): void {
    this.listeners.forEach((listener) => listener(key))
  }
}

and in jest.setup.ts:

jest.mock("react-native-mmkv", () => ({
  __esModule: true,
  MMKV: MockMMKV,
  createMMKV: jest.fn(() => new MockMMKV()),
}))

wongk avatar Oct 31 '25 16:10 wongk

to create an mmkv instance, you should mock the createMMKV function.

  const mockStorage = new Map();
  return {
    createMMKV: () => ({
      set: (key, value) => {
        mockStorage.set(key, value);
      },
      getString: (key) => {
        const value = mockStorage.get(key);
        return typeof value === 'string' ? value : undefined;
      },
      getNumber: (key) => {
        const value = mockStorage.get(key);
        return typeof value === 'number' ? value : undefined;
      },
      getBoolean: (key) => {
        const value = mockStorage.get(key);
        return typeof value === 'boolean' ? value : undefined;
      },
      remove: (key) => {
        mockStorage.delete(key);
      },
      clearAll: () => {
        mockStorage.clear();
      },
      contains: (key) => {
        return mockStorage.has(key);
      },
      getAllKeys: () => {
        return Array.from(mockStorage.keys());
      },
    }),
  };
});```

necmettindev avatar Nov 02 '25 13:11 necmettindev

There is an answer in nitro repository https://github.com/mrousavy/nitro/issues/812#issuecomment-3425515066

zatteo avatar Nov 03 '25 13:11 zatteo

There is createMockMMKV

mrousavy avatar Nov 03 '25 20:11 mrousavy

@zatteo This did not work for me:

jest.mock('react-native-nitro-modules', () => {
    return {
        NitroModules: () => {
            return {};
        },
    };
});

I mocked mine like this, no issue so far.

export const createMMKV = () => ({
  getString: jest.fn(),
  set: jest.fn(),
  delete: jest.fn(),
});
Image

GregPetropoulos avatar Nov 05 '25 02:11 GregPetropoulos

Adding the following before running my Jest tests was enough:

jest.mock("react-native-nitro-modules", () => {
  return {
    createHybridObject: jest.fn(() => {
      // Return a mock object that won't be used since MMKV has its own mock
      return {}
    }),
  }
})

we might need to update/fix the mock here to contain the mock i posted above: https://github.com/mrousavy/react-native-mmkv/blob/main/packages/react-native-mmkv/mocks/react-native-nitro-modules.js

tastydev avatar Nov 06 '25 00:11 tastydev