How to test Async Storage with Jest? How to test Async Storage with Jest? reactjs reactjs

How to test Async Storage with Jest?


For everyone who sees this question in > 2019:

Since Nov 2020, AsyncStorage was renamed back to @react-native-async-storage/async-storage", which causes this warning to appear if you're importing it from react-native:

Warning: Async Storage has been extracted from react-native core and will be removed in a future release.

The new module includes its own mock, so you don't have to worry about writing your own anymore.

Per the project's documentation, you can set it up in 2 different ways:

##With mocks directory

  • In your project root directory, create a __mocks__/@react-native-community directory.
  • Inside that folder, create async-storage.js file.
  • Inside that file, export Async Storage mock.
    export default from '@react-native-async-storage/async-storage/jest/async-storage-mock'

Jest should then mock AsyncStorage by default in all your tests. If it doesn't, try calling jest.mock(@react-native-async-storage/async-storage) at the top of your test file.

With Jest setup file

  • In your Jest config (probably in package.json or jest.config.js) add the setup file's location:
    "jest": {  "setupFiles": ["./path/to/jestSetupFile.js"]}
  • Inside your setup file, set up the AsyncStorage mock:
    import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock';jest.mock('@react-native-community/async-storage', () => mockAsyncStorage);

If you're using TypeScript, using the 2nd option (Jest setup file) is way easier, since with the 1st one (mocks directory) it won't associate @types/react-native-community__async-storage with the mock automatically.


May be you can try something like this:

mockStorage.js

export default class MockStorage {  constructor(cache = {}) {    this.storageCache = cache;  }  setItem = jest.fn((key, value) => {    return new Promise((resolve, reject) => {      return (typeof key !== 'string' || typeof value !== 'string')        ? reject(new Error('key and value must be string'))        : resolve(this.storageCache[key] = value);    });  });  getItem = jest.fn((key) => {    return new Promise((resolve) => {      return this.storageCache.hasOwnProperty(key)        ? resolve(this.storageCache[key])        : resolve(null);    });  });  removeItem = jest.fn((key) => {    return new Promise((resolve, reject) => {      return this.storageCache.hasOwnProperty(key)        ? resolve(delete this.storageCache[key])        : reject('No such key!');    });  });  clear = jest.fn((key) => {    return new Promise((resolve, reject) =>  resolve(this.storageCache = {}));  });  getAllKeys = jest.fn((key) => {    return new Promise((resolve, reject) => resolve(Object.keys(this.storageCache)));  });}

and inside your test file:

import MockStorage from './MockStorage';const storageCache = {};const AsyncStorage = new MockStorage(storageCache);jest.setMock('AsyncStorage', AsyncStorage)// ... do things


My original answer just pointed at how the author of react-native-simple-store had dealt with the mocking. I've updated my answer with my own mocking that removes Jason's hard-coded mock responses.

Jason Merino has a nice simple approach to this in https://github.com/jasonmerino/react-native-simple-store/blob/master/tests/index-test.js#L31-L64

jest.mock('react-native', () => ({AsyncStorage: {    setItem: jest.fn(() => {        return new Promise((resolve, reject) => {            resolve(null);        });    }),    multiSet:  jest.fn(() => {        return new Promise((resolve, reject) => {            resolve(null);        });    }),    getItem: jest.fn(() => {        return new Promise((resolve, reject) => {            resolve(JSON.stringify(getTestData()));        });    }),    multiGet: jest.fn(() => {        return new Promise((resolve, reject) => {            resolve(multiGetTestData());        });    }),    removeItem: jest.fn(() => {        return new Promise((resolve, reject) => {            resolve(null);        });    }),    getAllKeys: jest.fn(() => {        return new Promise((resolve) => {            resolve(['one', 'two', 'three']);        });    })  }}));

My own mock:

const items = {};jest.mock('react-native', () => ({AsyncStorage: {            setItem: jest.fn((item, value) => {        return new Promise((resolve, reject) => {            items[item] = value;            resolve(value);        });    }),    multiSet:  jest.fn((item, value) => {        return new Promise((resolve, reject) => {    items[item] = value;            resolve(value);        });    }),    getItem: jest.fn((item, value) => {        return new Promise((resolve, reject) => {            resolve(items[item]);        });    }),    multiGet: jest.fn((item) => {        return new Promise((resolve, reject) => {            resolve(items[item]);        });    }),    removeItem: jest.fn((item) => {        return new Promise((resolve, reject) => {            resolve(delete items[item]);        });    }),    getAllKeys: jest.fn((items) => {        return new Promise((resolve) => {            resolve(items.keys());        });    })  }}));