Как протестировать Async Storage с помощью Jest?
Я создаю приложение с React Native. Я хочу свести к минимуму, как часто я общаюсь с базой данных, поэтому я активно использую AsyncStorage. Там много места для ошибок в переводе между БД и AsyncStorage. Поэтому я хочу убедиться, что AsyncStorage имеет данные, которые, как я полагаю, он делает, запуская автоматические тесты против него. Удивительно, но я не нашел никакой информации о том, как это сделать в Интернете. Мои попытки сделать это сами по себе не сработали.
Использование Jest:
it("can read asyncstorage", () => {
return AsyncStorage.getItem('foo').then(foo => {
expect(foo).not.toBe("");
}); });
Этот метод завершился с ошибкой:
TypeError: RCTAsyncStorage.multiGet is not a function
Удаление возврата приведет к его немедленному запуску, не дожидаясь значения и неправильно пройти тест.
Я получил одну и ту же ошибку, когда пытался проверить ее с помощью ключевого слова wait:
it('can read asyncstorage', async () => {
this.foo = "";
await AsyncStorage.getItem('foo').then(foo => {
this.foo = foo;
});
expect(foo).not.toBe(""); });
Любые предложения по успешному запуску утверждений против значений в AsyncStorage? Я предпочел бы продолжать использовать Jest, но если это можно сделать только с помощью некоторой альтернативной библиотеки тестирования, я открыт для этого.
Ответы
Ответ 1
Мой первоначальный ответ просто указал на то, как автор реакции-родной-простой-магазин занимался насмешкой. Я обновил свой ответ своим собственным издевательством, который удаляет отпечатки Джейсона с жестким кодированием.
Джейсон Мерино имеет простой простой подход к этому в 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']);
});
})
}
}));
Мой собственный макет:
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());
});
})
}
}));
Ответ 2
Может быть, вы можете попробовать что-то вроде этого:
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)));
});
}
и внутри вашего тестового файла:
import MockStorage from './MockStorage';
const storageCache = {};
const AsyncStorage = new MockStorage(storageCache);
jest.setMock('AsyncStorage', AsyncStorage)
// ... do things
Ответ 3
Я думаю, что jest.setMock может быть в этом случае лучше, чем jest.mock поэтому мы можем использовать react-native
без проблем просто насмешливых AsyncStorage
так:
jest.setMock('AsyncStorage', {
getItem: jest.fn(
item =>
new Promise((resolve, reject) => {
resolve({ myMockObjectToReturn: 'myMockObjectToReturn' });
})
),
});
Ответ 4
Для всех, кто видит этот вопрос в> 2019:
С февраля 2019 года AsyncStorage был перемещен в @ act -native-community/async-storage, что приводит к появлению этого предупреждения, если вы импортируете его из react-native
:
Warning: Async Storage has been extracted from react-native core and will be removed in a future release.
Новый модуль включает в себя собственный макет, так что вам не нужно больше беспокоиться о написании своего собственного.
В соответствии с проектной документацией вы можете настроить его двумя различными способами:
С каталогом издевательств
С установочным файлом Jest
- В вашей конфигурации Jest (вероятно, в
package.json
или jest.config.js
) добавьте расположение файла установки: "jest": {
"setupFiles": ["./path/to/jestSetupFile.js"]
}
-
Внутри вашего установочного файла настройте макет AsyncStorage:
import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock';
jest.mock('@react-native-community/async-storage', () => mockAsyncStorage);
Если вы используете TypeScript, использовать 2-й вариант (установочный файл Jest) гораздо проще, поскольку с 1-м вариантом (каталог mocks) он не будет автоматически связывать @types/react-native-community__async-storage
с mock.
Ответ 5
Для кого-то еще, чтобы получить здесь, asyncStorage также нуждается в обратном вызове, некоторые библиотеки используют это