Rumah > Artikel > hujung hadapan web > Pengenalan kepada Jest: Ujian Unit, Mengejek dan Kod Asynchronous
Jest ialah perpustakaan untuk menguji kod JavaScript.
Ia adalah projek sumber terbuka yang diselenggara oleh Facebook, dan ia amat sesuai untuk ujian kod React, walaupun tidak terhad kepada itu: ia boleh menguji mana-mana kod JavaScript. Kekuatannya ialah:
export default function sum(a, n) { return a + b; }
divide.test.js
import sum from './sum'; // Describe the test and wrap it in a function. it('adds 1 + 2 to equal 3', () => { const result = sum(1, 2); // Jest uses matchers, like pretty much any other JavaScript testing framework. // They're designed to be easy to get at a glance; // here, you're expecting `result` to be 3. expect(result).toBe(3); });
Penjodoh ialah kaedah yang membolehkan anda menguji nilai.
Pergantungan ialah sekeping kod yang bergantung pada aplikasi anda. Ia boleh menjadi fungsi/Objek dalam projek kami atau pergantungan pihak ketiga (ex axios)
Sekeping kod menjadi kebergantungan sebenar apabila aplikasi anda sendiri tidak dapat berfungsi tanpanya.
Sebagai contoh, jika anda melaksanakan ciri dalam aplikasi anda untuk menghantar e-mel atau membuat permintaan api atau membina objek konfigurasi dll
Terdapat dua cara yang boleh kami tambahkan kebergantungan dalam kod kami dalam projek js:
export default function sum(a, n) { return a + b; }
Sekadar istilah mewah pada konsep yang mudah.
Jika fungsi anda memerlukan beberapa kefungsian daripada kebergantungan luaran, hanya masukkannya sebagai hujah.
import sum from './sum'; // Describe the test and wrap it in a function. it('adds 1 + 2 to equal 3', () => { const result = sum(1, 2); // Jest uses matchers, like pretty much any other JavaScript testing framework. // They're designed to be easy to get at a glance; // here, you're expecting `result` to be 3. expect(result).toBe(3); });
Ujian unit ditulis dan dijalankan oleh pembangun perisian untuk memastikan bahagian aplikasi (dikenali sebagai "unit") memenuhi reka bentuknya dan berfungsi seperti yang dimaksudkan.
Kami ingin menguji kod kami secara berasingan, kami tidak mengambil berat tentang pelaksanaan sebenar sebarang kebergantungan.
Kami ingin mengesahkan
Dan di situlah ejekan kebergantungan kita berlaku.
Dalam ujian unit, olok-olok memberikan kami keupayaan untuk stub fungsi yang disediakan oleh kebergantungan dan bermaksud untuk memerhatikan cara kod kami berinteraksi dengan kebergantungan.
Olok-olok amat berguna apabila mahal atau tidak praktikal untuk memasukkan pergantungan terus ke dalam ujian kami, contohnya, dalam kes di mana kod anda membuat panggilan HTTP ke API atau berinteraksi dengan lapisan pangkalan data.
Adalah lebih baik untuk menolak respons untuk kebergantungan ini, sambil memastikan bahawa ia dipanggil mengikut keperluan. Di sinilah ejekan berguna.
Dengan menggunakan fungsi olok-olok, kita boleh mengetahui perkara berikut:
Terdapat beberapa cara untuk mencipta fungsi olok-olok.
Kaedah jest.fn adalah, dengan sendirinya, fungsi tertib lebih tinggi.
Ia adalah kaedah kilang yang mencipta fungsi olok-olok baharu yang tidak digunakan.
Fungsi dalam JavaScript adalah warga kelas pertama, ia boleh dihantar sebagai hujah.
Setiap fungsi olok-olok mempunyai beberapa ciri istimewa. Harta olok-olok adalah asas. Sifat ini ialah objek yang mempunyai semua maklumat keadaan olok-olok tentang cara fungsi itu digunakan. Objek ini mengandungi tiga sifat tatasusunan:
export default function sum(a, n) { return a + b; }
import sum from './sum'; // Describe the test and wrap it in a function. it('adds 1 + 2 to equal 3', () => { const result = sum(1, 2); // Jest uses matchers, like pretty much any other JavaScript testing framework. // They're designed to be easy to get at a glance; // here, you're expecting `result` to be 3. expect(result).toBe(3); });
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
// Constructor Injection // DatabaseManager class takes a database connector as a dependency class DatabaseManager { constructor(databaseConnector) { // Dependency injection of the database connector this.databaseConnector = databaseConnector; } updateRow(rowId, data) { // Use the injected database connector to perform the update this.databaseConnector.update(rowId, data); } } // parameter injection, takes a database connector instance in as an argument; easy to test! function updateRow(rowId, data, databaseConnector) { databaseConnector.update(rowId, data); }
Jenis ejekan ini kurang biasa atas beberapa sebab:
Pendekatan yang lebih biasa ialah menggunakan jest.mock untuk menetapkan semua eksport modul secara automatik kepada Fungsi Mock.
// 1. The mock function factory function fn(impl = () => {}) { // 2. The mock function const mockFn = function(...args) { // 4. Store the arguments used mockFn.mock.calls.push(args); mockFn.mock.instances.push(this); try { const value = impl.apply(this, args); // call impl, passing the right this mockFn.mock.results.push({ type: 'return', value }); return value; // return the value } catch (value) { mockFn.mock.results.push({ type: 'throw', value }); throw value; // re-throw the error } } // 3. Mock state mockFn.mock = { calls: [], instances: [], results: [] }; return mockFn; }
Kadangkala anda hanya mahu melihat kaedah dipanggil, tetapi mengekalkan pelaksanaan asal. Pada masa lain anda mungkin ingin mengejek pelaksanaan, tetapi pulihkan yang asal kemudian dalam suite.
test("returns undefined by default", () => { const mock = jest.fn(); let result = mock("foo"); expect(result).toBeUndefined(); expect(mock).toHaveBeenCalled(); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith("foo"); });
Pulihkan pelaksanaan asal
const doAdd = (a, b, callback) => { callback(a + b); }; test("calls callback with arguments added", () => { const mockCallback = jest.fn(); doAdd(1, 2, mockCallback); expect(mockCallback).toHaveBeenCalledWith(3); });
JavaScript adalah satu benang: hanya satu tugasan boleh dijalankan pada satu masa. Biasanya itu bukan masalah besar, tetapi sekarang bayangkan anda menjalankan tugas yang mengambil masa 30 saat.. Ya.. Semasa tugasan itu kami menunggu selama 30 saat sebelum perkara lain boleh berlaku (JavaScript berjalan pada utas utama penyemak imbas secara lalai, jadi keseluruhan UI tersekat).
Sekarang tahun 2020, tiada siapa yang mahukan tapak web yang lambat dan tidak responsif.
Mujurlah, penyemak imbas memberikan kami beberapa ciri yang tidak disediakan oleh enjin JavaScript itu sendiri: API Web. Ini termasuk DOM API, setTimeout, permintaan HTTP dan sebagainya. Ini boleh membantu kami mencipta beberapa tak segerak, gelagat tidak menyekat
export default function sum(a, n) { return a + b; }
import sum from './sum'; // Describe the test and wrap it in a function. it('adds 1 + 2 to equal 3', () => { const result = sum(1, 2); // Jest uses matchers, like pretty much any other JavaScript testing framework. // They're designed to be easy to get at a glance; // here, you're expecting `result` to be 3. expect(result).toBe(3); });
Jest biasanya mengharapkan untuk melaksanakan fungsi ujian segera.
Jika kami melakukan operasi tak segerak, tetapi kami tidak memberitahu Jest bahawa ia sepatutnya menunggu sehingga ujian tamat, ia akan memberikan positif palsu.
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
Corak Tak Segerak
Terdapat beberapa corak untuk mengendalikan operasi async dalam JavaScript; yang paling banyak digunakan ialah:
Anda tidak boleh mempunyai ujian dalam panggilan balik, kerana Jest tidak akan melaksanakannya - pelaksanaan fail ujian tamat sebelum panggilan balik dipanggil. Untuk membetulkannya, hantar parameter kepada fungsi ujian, yang anda boleh panggil selesai dengan mudah. Jest akan menunggu sehingga anda memanggil done() sebelum menamatkan ujian itu:
// Constructor Injection // DatabaseManager class takes a database connector as a dependency class DatabaseManager { constructor(databaseConnector) { // Dependency injection of the database connector this.databaseConnector = databaseConnector; } updateRow(rowId, data) { // Use the injected database connector to perform the update this.databaseConnector.update(rowId, data); } } // parameter injection, takes a database connector instance in as an argument; easy to test! function updateRow(rowId, data, databaseConnector) { databaseConnector.update(rowId, data); }
Dengan fungsi yang mengembalikan janji, kami mengembalikan janji daripada ujian:
// 1. The mock function factory function fn(impl = () => {}) { // 2. The mock function const mockFn = function(...args) { // 4. Store the arguments used mockFn.mock.calls.push(args); mockFn.mock.instances.push(this); try { const value = impl.apply(this, args); // call impl, passing the right this mockFn.mock.results.push({ type: 'return', value }); return value; // return the value } catch (value) { mockFn.mock.results.push({ type: 'throw', value }); throw value; // re-throw the error } } // 3. Mock state mockFn.mock = { calls: [], instances: [], results: [] }; return mockFn; }
Untuk menguji fungsi yang mengembalikan janji, kami juga boleh menggunakan async/menunggu, yang menjadikan sintaks sangat mudah dan mudah:
test("returns undefined by default", () => { const mock = jest.fn(); let result = mock("foo"); expect(result).toBeUndefined(); expect(mock).toHaveBeenCalled(); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith("foo"); });
const doAdd = (a, b, callback) => { callback(a + b); }; test("calls callback with arguments added", () => { const mockCallback = jest.fn(); doAdd(1, 2, mockCallback); expect(mockCallback).toHaveBeenCalledWith(3); });
Atas ialah kandungan terperinci Pengenalan kepada Jest: Ujian Unit, Mengejek dan Kod Asynchronous. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!