itinance / react-native-fs

Native filesystem access for react-native
MIT License
4.95k stars 977 forks source link

Testing with jest: Invariant Violation: Native module cannot be null #970

Open ghasemikasra39 opened 3 years ago

ghasemikasra39 commented 3 years ago

I get this error only in testing environment

yarn run v1.22.4
$ jest App.test.tsx
 FAIL  __tests__/App.test.tsx
  ● Test suite failed to run

    Invariant Violation: Native module cannot be null.

      2 | import FormData from 'react-native/Libraries/Network/FormData';
      3 | import { store } from '../../store';
    > 4 | import RNFS from 'react-native-fs';
        | ^
      5 | import { actionCreators } from '../../store/actions';
      6 | import InitialLoadingService from '../utility/InitialLoadingService';
      7 |

      at invariant (node_modules/invariant/invariant.js:40:15)
      at new NativeEventEmitter (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:37:7)
      at Object.<anonymous> (node_modules/react-native-fs/FS.common.js:14:31)
      at Object.<anonymous> (src/services/api/UserProfileManager.ts:4:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        12.178s
Ran all test suites matching /App.test.tsx/i.
/Users/kasra/Documents/youpendo/youpendo-app-bareworkflow/node_modules/redux-persist/lib/createPersistoid.js:98
    writePromise = storage.setItem(storageKey, serialize(stagedState)).catch(onWriteFail);
                                                                      ^

TypeError: Cannot read property 'catch' of undefined
    at writeStagedState (/Users/kasra/Documents/youpendo/youpendo-app-bareworkflow/node_modules/redux-persist/lib/createPersistoid.js:98:71)
    at Timeout.processNextKey [as _onTimeout] (/Users/kasra/Documents/youpendo/youpendo-app-bareworkflow/node_modules/redux-persist/lib/createPersistoid.js:87:7)
    at listOnTimeout (internal/timers.js:531:17)
    at processTimers (internal/timers.js:475:7)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

mocking did not help:

jest.mock('react-native-fs', () => {
  return {
    readFile: jest.fn(),
  };
});

adding react-native-fs to transformIgnorePatterns did not help

env:

"react-native-fs": "^2.16.6",
System:
    OS: macOS 11.0.1
    CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
    Memory: 140.95 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node
    Yarn: 1.22.4 - ~/Documents/youpendo/youpendo-app-bareworkflow/node_modules/.bin/yarn
    npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.9.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.3, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
    Android SDK:
      API Levels: 28, 29
      Build Tools: 28.0.3, 29.0.2
      System Images: android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6392135
    Xcode: 12.3/12C33 - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_232 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: ^4.8.0 => 4.13.0
    react: 16.13.1 => 16.13.1
    react-native: 0.63.3 => 0.63.3
ryanbourneuk commented 3 years ago

I've found the answers from https://github.com/itinance/react-native-fs/issues/404 really helpful - namely:

  1. Within the __mocks__ folder, create a file entitled react-native-fs.js
  2. In that folder, add your mocked functions like
export default {
    readFile: jest.fn(),
    ...
}

You may need to add a more complete mock however, as detailed here: https://github.com/itinance/react-native-fs/issues/404#issuecomment-360170580

I did not have to add react-native-fs to transformIgnorePatterns either.

hanayashiki commented 3 years ago

No luck with adding

jest.mock('react-native-fs', () => {
  return {
    readFile: jest.fn(),
  };
});

to setupFiles

this is so strange.

hanayashiki commented 3 years ago

Well in fact I have several mocks in the same setup file. When I move mockRNFS from the last one to the first one, it works. How can the order of mocking matter? Maybe it is a jest bug.

hubConnect commented 2 years ago

For future readers that run into an issue with mocking react-native-fs, I do my test mocks like:

jest.mock("react-native-fs", () => {
  const RNFS = {
    readFileAssets: async () => {
      return "testdata"
    },
  }

  return RNFS
})