Jawaban:
Solusi hebat dari @chiedo
Namun, kami menggunakan sintaks ES2015 dan saya merasa sedikit lebih bersih untuk menulisnya dengan cara ini.
class LocalStorageMock {
constructor() {
this.store = {};
}
clear() {
this.store = {};
}
getItem(key) {
return this.store[key] || null;
}
setItem(key, value) {
this.store[key] = value.toString();
}
removeItem(key) {
delete this.store[key];
}
};
global.localStorage = new LocalStorageMock;
|| null
sebabnya pengujian saya gagal, karena dalam pengujian saya saya gunakan not.toBeDefined()
. Solusi @Chiedo membuatnya bekerja lagi
Cari tahu dengan bantuan ini: https://groups.google.com/forum/#!topic/jestjs/9EPhuNWVYTg
Siapkan file dengan konten berikut:
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
},
removeItem: function(key) {
delete store[key];
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
Kemudian Anda menambahkan baris berikut ke package.json Anda di bawah konfigurasi Jest Anda
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
"setupFiles": [...]
berfungsi juga. Dengan opsi array, memungkinkan memisahkan tiruan menjadi file yang terpisah. Misalnya:"setupFiles": ["<rootDir>/__mocks__/localStorageMock.js"]
getItem
sedikit berbeda dengan apa yang akan dikembalikan oleh browser jika tidak ada data yang ditetapkan terhadap kunci tertentu. menelepon getItem("foo")
ketika tidak diatur misalnya akan kembali null
di browser, tetapi undefined
dengan tiruan ini - ini menyebabkan salah satu pengujian saya gagal. Solusi sederhana bagi saya adalah kembali store[key] || null
ke getItem
fungsi
localStorage['test'] = '123'; localStorage.getItem('test')
Jika menggunakan aplikasi create-react, ada solusi yang lebih sederhana dan langsung dijelaskan dalam dokumentasi .
Buat src/setupTests.js
dan letakkan ini di dalamnya:
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
Kontribusi Tom Mertz dalam komentar di bawah:
Anda kemudian dapat menguji bahwa fungsi localStorageMock Anda digunakan dengan melakukan sesuatu seperti
expect(localStorage.getItem).toBeCalledWith('token')
// or
expect(localStorage.getItem.mock.calls.length).toBe(1)
di dalam tes Anda jika Anda ingin memastikan itu dipanggil. Lihat https://facebook.github.io/jest/docs/en/mock-functions.html
localStorage
Anda gunakan dalam kode Anda. (jika Anda menggunakan create-react-app
dan semua skrip otomatis yang disediakannya secara alami)
expect(localStorage.getItem).toBeCalledWith('token')
atau expect(localStorage.getItem.mock.calls.length).toBe(1)
di dalam tes Anda jika Anda ingin memastikan itu dipanggil. Lihat facebook.github.io/jest/docs/en/mock-functions.html
localStorage
? Tidakkah Anda ingin mengatur ulang mata-mata setelah setiap tes untuk mencegah "limpahan" ke dalam tes lain?
Saat ini (Oktober '19) penyimpanan lokal tidak dapat diejek atau dimata-matai dengan bercanda seperti yang biasa Anda lakukan, dan sebagaimana diuraikan dalam dokumen app-react-app. Ini karena perubahan yang dilakukan di jsdom. Anda bisa membacanya di gurauan dan kegelisahan pelacak masalah .
Sebagai solusinya, Anda dapat memata-matai prototipe sebagai gantinya:
// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();
// works:
jest.spyOn(window.localStorage.__proto__, 'setItem');
window.localStorage.__proto__.setItem = jest.fn();
// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();
jest.spyOn(window.localStorage.__proto__, 'setItem');
atau Anda hanya mengambil paket tiruan seperti ini:
https://www.npmjs.com/package/jest-localstorage-mock
tidak hanya menangani fungsi penyimpanan tetapi juga memungkinkan Anda menguji apakah toko itu benar-benar dipanggil.
Alternatif yang lebih baik yang menangani undefined
nilai (tidak ada toString()
) dan kembali null
jika nilai tidak ada. Menguji ini dengan react
v15, redux
danredux-auth-wrapper
class LocalStorageMock {
constructor() {
this.store = {}
}
clear() {
this.store = {}
}
getItem(key) {
return this.store[key] || null
}
setItem(key, value) {
this.store[key] = value
}
removeItem(key) {
delete this.store[key]
}
}
global.localStorage = new LocalStorageMock
removeItem
: developer.mozilla.org/en-US/docs/Web/API/Storage/removeItem
Jika Anda mencari tiruan dan bukan sebuah rintisan, berikut adalah solusi yang saya gunakan:
export const localStorageMock = {
getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
setItem: jest.fn().mockImplementation((key, value) => {
localStorageItems[key] = value;
}),
clear: jest.fn().mockImplementation(() => {
localStorageItems = {};
}),
removeItem: jest.fn().mockImplementation((key) => {
localStorageItems[key] = undefined;
}),
};
export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports
Saya mengekspor item penyimpanan agar mudah diinisialisasi. Yaitu saya dapat dengan mudah mengaturnya ke objek
Di versi Jest + JSDom yang lebih baru tidak mungkin untuk mengatur ini, tetapi penyimpanan lokal sudah tersedia dan Anda dapat memata-matai itu seperti ini:
const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');
Saya menemukan solusi ini dari github
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Anda dapat memasukkan kode ini di setupTests Anda dan itu akan berfungsi dengan baik.
Saya mengujinya dalam proyek dengan typesctipt.
Sayangnya, solusi yang saya temukan di sini tidak berhasil untuk saya.
Jadi saya melihat masalah Jest GitHub dan menemukan utas ini
Solusi yang paling banyak dipilih adalah:
const spy = jest.spyOn(Storage.prototype, 'setItem');
// or
Storage.prototype.getItem = jest.fn(() => 'bla');
window
atau Storage
mendefinisikan. Mungkin itu versi lama Jest yang saya gunakan.
Sebagai @ ck4 disarankan dokumentasi memiliki penjelasan yang jelas untuk digunakan localStorage
dalam bercanda. Namun fungsi tiruan gagal menjalankan salah satulocalStorage
metode.
Di bawah ini adalah contoh terperinci dari komponen reaksi saya yang memanfaatkan metode abstrak untuk menulis dan membaca data,
//file: storage.js
const key = 'ABC';
export function readFromStore (){
return JSON.parse(localStorage.getItem(key));
}
export function saveToStore (value) {
localStorage.setItem(key, JSON.stringify(value));
}
export default { readFromStore, saveToStore };
Kesalahan:
TypeError: _setupLocalStorage2.default.setItem is not a function
Fix:
Tambah bawah fungsi mock untuk bercanda (path: .jest/mocks/setUpStore.js
)
let mockStorage = {};
module.exports = window.localStorage = {
setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
getItem: (key) => mockStorage[key],
clear: () => mockStorage = {}
};
Cuplikan direferensikan dari sini
Riffed off beberapa jawaban lain di sini untuk menyelesaikannya untuk proyek dengan naskah. Saya membuat LocalStorageMock seperti ini:
export class LocalStorageMock {
private store = {}
clear() {
this.store = {}
}
getItem(key: string) {
return this.store[key] || null
}
setItem(key: string, value: string) {
this.store[key] = value
}
removeItem(key: string) {
delete this.store[key]
}
}
Kemudian saya membuat kelas LocalStorageWrapper yang saya gunakan untuk semua akses ke penyimpanan lokal di aplikasi alih-alih secara langsung mengakses variabel penyimpanan lokal global. Memudahkan untuk mengatur tiruan di bungkusnya untuk tes.
describe('getToken', () => {
const Auth = new AuthService();
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik1yIEpvc2VwaCIsImlkIjoiNWQwYjk1Mzg2NTVhOTQ0ZjA0NjE5ZTA5IiwiZW1haWwiOiJ0cmV2X2pvc0Bob3RtYWlsLmNvbSIsInByb2ZpbGVVc2VybmFtZSI6Ii9tcmpvc2VwaCIsInByb2ZpbGVJbWFnZSI6Ii9Eb3Nlbi10LUdpci1sb29rLWN1dGUtbnVrZWNhdDMxNnMtMzExNzAwNDYtMTI4MC04MDAuanBnIiwiaWF0IjoxNTYyMzE4NDA0LCJleHAiOjE1OTM4NzYwMDR9.YwU15SqHMh1nO51eSa0YsOK-YLlaCx6ijceOKhZfQZc';
beforeEach(() => {
global.localStorage = jest.fn().mockImplementation(() => {
return {
getItem: jest.fn().mockReturnValue(token)
}
});
});
it('should get the token from localStorage', () => {
const result = Auth.getToken();
expect(result).toEqual(token);
});
});
Buat tiruan dan tambahkan ke global
objekt
Anda perlu mengejek penyimpanan lokal dengan cuplikan ini
// localStorage.js
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Dan dalam konfigurasi bercanda:
"setupFiles":["localStorage.js"]
Jangan ragu untuk bertanya apa pun.
Solusi berikut ini kompatibel untuk menguji dengan ketat naskah, ESLint, TSLint, dan lebih cantik config: { "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
:
class LocalStorageMock {
public store: {
[key: string]: string
}
constructor() {
this.store = {}
}
public clear() {
this.store = {}
}
public getItem(key: string) {
return this.store[key] || undefined
}
public setItem(key: string, value: string) {
this.store[key] = value.toString()
}
public removeItem(key: string) {
delete this.store[key]
}
}
/* tslint:disable-next-line:no-any */
;(global as any).localStorage = new LocalStorageMock()
HT / https://stackoverflow.com/a/51583401/101290 untuk cara memperbarui global.localStorage
Untuk melakukan hal yang sama dalam naskah, lakukan hal berikut:
Siapkan file dengan konten berikut:
let localStorageMock = (function() {
let store = new Map()
return {
getItem(key: string):string {
return store.get(key);
},
setItem: function(key: string, value: string) {
store.set(key, value);
},
clear: function() {
store = new Map();
},
removeItem: function(key: string) {
store.delete(key)
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
Kemudian Anda menambahkan baris berikut ke package.json Anda di bawah konfigurasi Jest Anda
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
Atau Anda mengimpor file ini dalam test case di mana Anda ingin mengejek penyimpanan lokal.
value + ''
di setter untuk menangani nilai nol dan tidak terdefinisi dengan benar