Apakah ada perpustakaan di luar sana untuk diolok-olok localStorage
?
Saya telah menggunakan Sinon.JS untuk sebagian besar ejekan javascript saya yang lain dan merasa sangat hebat.
Pengujian awal saya menunjukkan bahwa localStorage menolak untuk ditugaskan di firefox (sadface) jadi saya mungkin perlu semacam peretasan untuk ini: /
Pilihan saya saat ini (seperti yang saya lihat) adalah sebagai berikut:
- Buat fungsi pembungkus yang digunakan semua kode saya dan tiru itu
- Buat semacam manajemen status (mungkin rumit) (snapshot localStorage sebelum pengujian, di snapshot pemulihan pembersihan) untuk localStorage.
??????
Apa pendapat Anda tentang pendekatan ini dan apakah menurut Anda ada cara lain yang lebih baik untuk melakukannya? Either way saya akan menempatkan "perpustakaan" yang dihasilkan yang akhirnya saya buat di github untuk kebaikan open source.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
sumber
sumber
Profit!
Jawaban:
Berikut cara sederhana untuk mengejeknya dengan Jasmine:
Jika Anda ingin meniru penyimpanan lokal dalam semua pengujian Anda, nyatakan
beforeEach()
fungsi yang ditampilkan di atas dalam cakupan global pengujian Anda (tempat biasanya adalah skrip specHelper.js ).sumber
ReferenceError: localStorage is not defined
(menjalankan tes menggunakan FB Jest dan npm)… ada ide bagaimana untuk menyiasatinya?window.localStorage
andCallFake
diubah menjadiand.callFake
di Jasmine 2. +cukup mengejek localStorage / sessionStorage global (mereka memiliki API yang sama) untuk kebutuhan Anda.
Sebagai contoh:
Dan kemudian apa yang sebenarnya Anda lakukan, adalah seperti itu:
sumber
getItem
harus dikembalikannull
jika nilai tidak adareturn storage[key] || null;
:;localStorage
secara keseluruhan tidak mungkin.storage[key] || null
tidak benar. Jikastorage[key] === 0
akan kembalinull
sebagai gantinya. Saya pikir Anda bisa melakukannyareturn key in storage ? storage[key] : null
.function storageMock() { var storage = {}; return { setItem: function(key, value) { storage[key] = value || ''; }, getItem: function(key) { return key in storage ? storage[key] : null; }, removeItem: function(key) { delete storage[key]; }, get length() { return Object.keys(storage).length; }, key: function(i) { var keys = Object.keys(storage); return keys[i] || null; } }; } window.localStor = storageMock();
TypeError: Cannot set property localStorage of #<Window> which has only a getter
, tahu bagaimana cara memperbaikinya?Pertimbangkan juga opsi untuk memasukkan dependensi dalam fungsi konstruktor objek.
Sejalan dengan mocking dan pengujian unit, saya ingin menghindari pengujian implementasi penyimpanan. Misalnya tidak ada gunanya memeriksa apakah panjang penyimpanan bertambah setelah Anda mengatur item, dll.
Karena jelas tidak dapat diandalkan untuk mengganti metode pada objek localStorage yang sebenarnya, gunakan mockStorage "dumb" dan hentikan metode individual seperti yang diinginkan, seperti:
sumber
Inilah yang saya lakukan...
sumber
Solusi saat ini tidak akan berfungsi di Firefox. Ini karena localStorage didefinisikan oleh spesifikasi html sebagai tidak dapat dimodifikasi. Namun Anda bisa menyiasatinya dengan mengakses prototipe localStorage secara langsung.
Solusi lintas browser adalah mengejek objek pada
Storage.prototype
misbukannya spyOn (localStorage, 'setItem') digunakan
diambil dari balasan bzbarsky dan teogeos di sini https://github.com/jasmine/jasmine/issues/299
sumber
Saya baru saja menulis satu:
Hanya dalam konteks global. Dengan fungsi pembungkus seperti di atas, ini berfungsi dengan baik.
sumber
var window = { localStorage: ... }
localStorage
, tes tidak haruslocalStorage
langsung di dalamnya. Solusi ini tidak mengubahlocalStorage
untuk skrip lain jadi ini bukan solusi. +1 untuk trik pelingkupanif this.hasOwnProperty(key) return this[key] else return null
Berikut adalah contoh penggunaan sinon spy dan mock:
sumber
Menimpa
localStorage
propertiwindow
objek global seperti yang disarankan dalam beberapa jawaban tidak akan berfungsi di sebagian besar mesin JS, karena mereka mendeklarasikanlocalStorage
properti data sebagai tidak dapat ditulis dan tidak dapat dikonfigurasi.Namun saya menemukan bahwa setidaknya dengan versi WebKit PhantomJS (versi 1.9.8) Anda dapat menggunakan API lama
__defineGetter__
untuk mengontrol apa yang terjadi jikalocalStorage
diakses. Tetap akan menarik jika ini berfungsi di browser lain juga.Manfaat dari pendekatan ini adalah Anda tidak perlu mengubah kode yang akan Anda uji.
sumber
Anda tidak harus meneruskan objek penyimpanan ke setiap metode yang menggunakannya. Sebagai gantinya, Anda dapat menggunakan parameter konfigurasi untuk modul apa pun yang menyentuh adaptor penyimpanan.
Modul lama Anda
Modul baru Anda dengan fungsi config "wrapper"
Saat Anda menggunakan modul dalam menguji kode
The
MockStorage
kelas akan terlihat seperti iniSaat menggunakan modul Anda dalam kode produksi, teruskan adaptor localStorage yang sebenarnya
sumber
export default function
dan inisialisasi modul dengan argumen seperti itu hanya es6. polanya tetap berdiri sendiri.require
untuk mengimpor modul dan menerapkannya ke argumen dalam ekspresi yang sama. Tidak ada cara untuk melakukan itu di ES6 yang saya tahu. Kalau tidak, saya akan menggunakan ES6import
Saya memutuskan untuk mengulangi komentar saya atas jawaban Pumbaa80 sebagai jawaban terpisah agar lebih mudah untuk digunakan kembali sebagai perpustakaan.
Saya mengambil kode Pumbaa80, memperbaikinya sedikit, menambahkan tes dan menerbitkannya sebagai modul npm di sini: https://www.npmjs.com/package/mock-local-storage .
Berikut ini kode sumbernya: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Beberapa tes: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
Modul membuat localStorage dan sessionStorage tiruan pada objek global (jendela atau global, yang mana yang ditentukan).
Dalam pengujian proyek saya yang lain, saya memerlukannya dengan mocha seperti ini:
mocha -r mock-local-storage
untuk membuat definisi global tersedia untuk semua kode yang diuji.Pada dasarnya, kode terlihat seperti berikut:
Perhatikan bahwa semua metode ditambahkan melalui
Object.defineProperty
sehingga tidak akan diulang, diakses atau dihapus sebagai item biasa dan tidak akan dihitung panjangnya. Juga saya menambahkan cara untuk mendaftarkan callback yang dipanggil ketika sebuah item akan dimasukkan ke dalam objek. Callback ini dapat digunakan untuk meniru kesalahan kuota terlampaui dalam pengujian.sumber
Saya menemukan bahwa saya tidak perlu mengejeknya. Saya dapat mengubah penyimpanan lokal sebenarnya ke keadaan yang saya inginkan
setItem
, lalu menanyakan nilai untuk melihat apakah itu berubah melaluigetItem
. Ini tidak sekuat mengejek karena Anda tidak dapat melihat berapa kali sesuatu diubah, tetapi berhasil untuk tujuan saya.sumber
Sayangnya, satu-satunya cara kita dapat memalsukan objek localStorage dalam skenario pengujian adalah dengan mengubah kode yang kita uji. Anda harus membungkus kode Anda dalam fungsi anonim (yang seharusnya Anda lakukan) dan menggunakan "injeksi ketergantungan" untuk meneruskan referensi ke objek jendela. Sesuatu seperti:
Kemudian, di dalam pengujian Anda, Anda dapat menentukan:
sumber
Ini adalah cara saya melakukannya. Buat tetap sederhana.
sumber
kredit ke https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Membuat penyimpanan lokal palsu, dan memata-matai penyimpanan lokal, saat disimpan
Dan di sini kami menggunakannya
sumber