Mirage JS Deep Dive: Memahami Pabrik, Perlengkapan, dan Serializer (Bagian 2)
Diterbitkan: 2022-03-10Dalam artikel sebelumnya dari seri ini, kami mempelajari Model dan Asosiasi yang terkait dengan Mirage. Saya menjelaskan bahwa Model memungkinkan kita untuk membuat data tiruan dinamis yang akan disajikan Mirage ke aplikasi kita saat membuat permintaan ke titik akhir tiruan kita. Pada artikel ini, kita akan melihat tiga fitur Mirage lainnya yang memungkinkan API mocking yang lebih cepat. Mari selami!
Catatan : Saya sangat merekomendasikan membaca dua artikel pertama saya jika Anda belum benar-benar memahami apa yang akan dibahas di sini. Namun Anda masih bisa mengikuti dan merujuk artikel sebelumnya bila perlu.
- Menyiapkan API Mocking Dengan Mirage JS Dan Vue
- Model dan Asosiasi Mirage JS
Pabrik
Dalam artikel sebelumnya, saya menjelaskan bagaimana Mirage JS digunakan untuk mengejek API backend, sekarang mari kita asumsikan kita mengejek sumber daya produk di Mirage. Untuk mencapai ini, kami akan membuat penangan rute yang akan bertanggung jawab untuk mencegat permintaan ke titik akhir tertentu, dan dalam hal ini, titik akhir adalah api/products
. Handler rute yang kami buat akan mengembalikan semua produk. Di bawah ini adalah kode untuk mencapai ini di Mirage:
import { Server, Model } from 'miragejs'; new Server({ models: { product: Model, }, routes() { this.namespace = "api"; this.get('products', (schema, request) => { return schema.products.all() }) } }); },
Output dari hal di atas akan menjadi:
{ "products": [] }
Kita lihat dari output di atas bahwa product resource kosong. Namun ini diharapkan karena kami belum membuat catatan apa pun.
Kiat Pro : Mirage menyediakan singkatan yang diperlukan untuk titik akhir API konvensional. Jadi penangan rute di atas juga bisa sesingkat: this.get('/products')
.
Mari buat catatan model product
untuk disimpan di database Mirage menggunakan metode seeds
pada instance Server
kami:
seeds(server) { server.create('product', { name: 'Gemini Jacket' }) server.create('product', { name: 'Hansel Jeans' }) },
Hasil:
{ "products": [ { "name": "Gemini Jacket", "id": "1" }, { "name": "Hansel Jeans", "id": "2" } ] }
Seperti yang Anda lihat di atas, ketika aplikasi frontend kita membuat permintaan ke /api/products
, itu akan mendapatkan kembali kumpulan produk seperti yang didefinisikan dalam metode seeds
.
Menggunakan metode seeds
untuk menyemai database Mirage adalah langkah dari keharusan membuat setiap entri secara manual sebagai objek. Namun, tidak praktis untuk membuat 1000 (atau sejuta) catatan produk baru menggunakan pola di atas. Oleh karena itu kebutuhan akan pabrik .
Pabrik Dijelaskan
Pabrik adalah cara yang lebih cepat untuk membuat catatan database baru. Mereka memungkinkan kami untuk dengan cepat membuat beberapa catatan dari model tertentu dengan variasi untuk disimpan dalam database Mirage JS.
Pabrik juga merupakan objek yang memudahkan untuk menghasilkan data yang tampak realistis tanpa harus menyemai data tersebut satu per satu. Pabrik lebih merupakan resep atau cetak biru untuk membuat catatan dari model.
Membuat Pabrik
Mari kita periksa Pabrik dengan membuatnya. Pabrik yang akan kami buat akan digunakan sebagai cetak biru untuk membuat produk baru di database Mirage JS kami.
import { Factory } from 'miragejs' new Server({ // including the model definition for a better understanding of what's going on models: { product: Model }, factories: { product: Factory.extend({}) } })
Dari atas, Anda akan melihat kami menambahkan properti factory ke instance Server
kami dan mendefinisikan properti lain di dalamnya yang menurut konvensi memiliki nama yang sama dengan model yang ingin kami buatkan factories
, dalam hal ini, model tersebut adalah model product
. Cuplikan di atas menggambarkan pola yang akan Anda ikuti saat membuat pabrik di Mirage JS.
Meskipun kami memiliki pabrik untuk model product
, kami benar-benar belum menambahkan properti ke dalamnya. Properti pabrik dapat berupa tipe sederhana seperti string , boolean atau angka , atau fungsi yang mengembalikan data dinamis seperti yang akan kita lihat dalam implementasi lengkap pabrik produk baru kami di bawah ini:
import { Server, Model, Factory } from 'miragejs' new Server({ models: { product: Model }, factories: { product: Factory.extend({ name(i) { // i is the index of the record which will be auto incremented by Mirage JS return `Awesome Product ${i}`; // Awesome Product 1, Awesome Product 2, etc. }, price() { let minPrice = 20; let maxPrice = 2000; let randomPrice = Math.floor(Math.random() * (maxPrice - minPrice + 1)) + minPrice; return `$ ${randomPrice}`; }, category() { let categories = [ 'Electronics', 'Computing', 'Fashion', 'Gaming', 'Baby Products', ]; let randomCategoryIndex = Math.floor( Math.random() * categories.length ); let randomCategory = categories[randomCategoryIndex]; return randomCategory; }, rating() { let minRating = 0 let maxRating = 5 return Math.floor(Math.random() * (maxRating - minRating + 1)) + minRating; }, }), }, })
Dalam cuplikan kode di atas, kami menetapkan beberapa logika javascript melalui Math.random
untuk membuat data dinamis setiap kali pabrik digunakan untuk membuat catatan produk baru. Ini menunjukkan kekuatan dan fleksibilitas Pabrik.
Mari kita buat produk dengan memanfaatkan pabrik yang telah kita definisikan di atas. Untuk melakukan itu, kami memanggil server.create
dan meneruskan nama model ( product
) sebagai string. Mirage kemudian akan membuat rekor baru produk menggunakan pabrik produk yang kami tentukan. Kode yang Anda butuhkan untuk melakukannya adalah sebagai berikut:
new Server({ seeds(server) { server.create("product") } })
Kiat Pro : Anda dapat menjalankan console.log(server.db.dump())
untuk melihat catatan di database Mirage.
Sebuah record baru yang mirip dengan yang di bawah ini telah dibuat dan disimpan di database Mirage.
{ "products": [ { "rating": 3, "category": "Computing", "price": "$739", "name": "Awesome Product 0", "id": "1" } ] }
Mengganti pabrik
Kami dapat mengganti beberapa atau lebih nilai yang disediakan oleh pabrik dengan meneruskannya secara eksplisit seperti:
server.create("product", {name: "Yet Another Product", rating: 5, category: "Fashion" })
Catatan yang dihasilkan akan mirip dengan:
{ "products": [ { "rating": 5, "category": "Fashion", "price": "$782", "name": "Yet Another Product", "id": "1" } ] }
buat Daftar
Dengan pabrik di tempat, kita dapat menggunakan metode lain pada objek server yang disebut createList
. Metode ini memungkinkan pembuatan beberapa catatan dari model tertentu dengan meneruskan nama model dan jumlah catatan yang ingin Anda buat. Di bawah ini adalah penggunaannya:
server.createList("product", 10)
Atau
server.createList("product", 1000)
Seperti yang akan Anda amati, metode createList
di atas menggunakan dua argumen: nama model sebagai string dan bilangan bulat positif bukan-nol yang mewakili jumlah record yang akan dibuat. Jadi dari atas, kami baru saja membuat 500 catatan produk! Pola ini berguna untuk pengujian UI seperti yang akan Anda lihat di artikel berikutnya dari seri ini.
Perlengkapan
Dalam pengujian perangkat lunak, perlengkapan uji atau perlengkapan adalah keadaan sekumpulan atau kumpulan objek yang berfungsi sebagai dasar untuk menjalankan pengujian. Tujuan utama dari fixture adalah untuk memastikan bahwa lingkungan pengujian dikenal dengan baik agar hasil dapat diulang.
Mirage memungkinkan Anda membuat perlengkapan dan menggunakannya untuk menyemai basis data Anda dengan data awal.
Catatan : Anda disarankan untuk menggunakan factory 9 dari 10 kali karena mereka membuat tiruan Anda lebih mudah dipelihara.
Membuat Perlengkapan
Mari kita buat perlengkapan sederhana untuk memuat data ke database kita:
fixtures: { products: [ { id: 1, name: 'T-shirts' }, { id: 2, name: 'Work Jeans' }, ], },
Data di atas secara otomatis dimuat ke dalam database sebagai data awal Mirage. Namun, jika Anda memiliki fungsi seed yang ditentukan, Mirage akan mengabaikan perlengkapan Anda dengan asumsi bahwa Anda bermaksud menggantinya dan sebagai gantinya menggunakan pabrik untuk menyemai data Anda.
Perlengkapan Bersama Dengan Pabrik
Mirage membuat ketentuan bagi Anda untuk menggunakan Perlengkapan bersama Pabrik. Anda dapat mencapai ini dengan memanggil server.loadFixtures()
. Sebagai contoh:
fixtures: { products: [ { id: 1, name: "iPhone 7" }, { id: 2, name: "Smart TV" }, { id: 3, name: "Pressing Iron" }, ], }, seeds(server) { // Permits both fixtures and factories to live side by side server.loadFixtures() server.create("product") },
File perlengkapan
Idealnya, Anda ingin membuat perlengkapan Anda dalam file terpisah dari server.js
dan mengimpornya. Misalnya Anda dapat membuat direktori bernama fixtures
dan di dalamnya membuat products.js
. Di products.js
tambahkan:
// <PROJECT-ROOT>/fixtures/products.js export default [ { id: 1, name: 'iPhone 7' }, { id: 2, name: 'Smart TV' }, { id: 3, name: 'Pressing Iron' }, ];
Kemudian di server.js
impor dan gunakan perlengkapan produk seperti:
import products from './fixtures/products'; fixtures: { products, },
Saya menggunakan singkatan properti ES6 untuk menetapkan array produk yang diimpor ke properti products
dari objek perlengkapan.
Patut disebutkan bahwa perlengkapan akan diabaikan oleh Mirage JS selama pengujian kecuali Anda secara eksplisit melarangnya dengan menggunakan server.loadFixtures()
Pabrik vs. Jadwal
Menurut pendapat saya, Anda harus menghindari penggunaan perlengkapan kecuali Anda memiliki kasus penggunaan tertentu di mana mereka lebih cocok daripada pabrik. Perlengkapan cenderung lebih bertele-tele sementara pabrik lebih cepat dan melibatkan lebih sedikit penekanan tombol.
Serializer
Sangat penting untuk mengembalikan muatan JSON yang diharapkan ke frontend maka serializers .
Serializer adalah objek yang bertanggung jawab untuk mengubah **Model** atau **Collection** yang dikembalikan dari pengendali rute Anda menjadi payload JSON yang diformat seperti yang diharapkan oleh aplikasi frontend Anda.
Dokumen Mirage
Mari kita ambil penangan rute ini misalnya:
this.get('products/:id', (schema, request) => { return schema.products.find(request.params.id); });
Serializer bertanggung jawab untuk mengubah respons menjadi sesuatu seperti ini:
{ "product": { "rating": 0, "category": "Baby Products", "price": "$654", "name": "Awesome Product 1", "id": "2" } }
Serializer Bawaan Mirage JS
Untuk bekerja dengan serializer Mirage JS, Anda harus memilih serializer bawaan untuk memulai. Keputusan ini akan dipengaruhi oleh jenis JSON yang nantinya akan dikirim oleh backend Anda ke aplikasi front-end Anda. Mirage disertakan dengan serializer berikut:
-
JSONAPISerializer
Serializer ini mengikuti spesifikasi JSON:API. -
ActiveModelSerializer
Serializer ini dimaksudkan untuk meniru API yang menyerupai API Rails yang dibuat dengan permata active_model_serializer. -
RestSerializer
RestSerializer
adalah serializer "catch all" Mirage JS untuk API umum lainnya.
Definisi Serializer
Untuk menentukan serialisasi, impor serializer yang sesuai misalnya RestSerializer
dari miragejs
seperti:
import { Server, RestSerializer } from "miragejs"
Kemudian dalam contoh Server
:
new Server({ serializers: { application: RestSerializer, }, })
RestSerializer
digunakan oleh Mirage JS secara default. Jadi berlebihan untuk mengaturnya secara eksplisit. Cuplikan di atas adalah untuk tujuan teladan.
Mari kita lihat output dari JSONAPISerializer
dan ActiveModelSerializer
pada route handler yang sama seperti yang kita definisikan di atas
JSONAPISerializer
import { Server, JSONAPISerializer } from "miragejs" new Server({ serializers: { application: JSONAPISerializer, }, })
Hasil:
{ "data": { "type": "products", "id": "2", "attributes": { "rating": 3, "category": "Electronics", "price": "$1711", "name": "Awesome Product 1" } } }
ActiveModelSerializer
Untuk melihat ActiveModelSerializer bekerja, saya akan mengubah deklarasi category
di pabrik produk menjadi:
productCategory() { let categories = [ 'Electronics', 'Computing', 'Fashion', 'Gaming', 'Baby Products', ]; let randomCategoryIndex = Math.floor( Math.random() * categories.length ); let randomCategory = categories[randomCategoryIndex]; return randomCategory; },
Yang saya lakukan hanyalah mengubah nama properti menjadi productCategory
untuk menunjukkan bagaimana serializer akan menanganinya.
Kemudian, kami mendefinisikan serializer ActiveModelSerializer
seperti ini:
import { Server, ActiveModelSerializer } from "miragejs" new Server({ serializers: { application: ActiveModelSerializer, }, })
Serializer mengubah JSON yang dikembalikan sebagai:
{ "rating": 2, "product_category": "Computing", "price": "$64", "name": "Awesome Product 4", "id": "5" }
Anda akan melihat bahwa productCategory
telah diubah menjadi product_category
yang sesuai dengan permata active_model_serializer dari ekosistem Ruby.
Menyesuaikan Serializer
Mirage menyediakan kemampuan untuk menyesuaikan serializer. Katakanlah aplikasi Anda membutuhkan nama atribut Anda untuk di-camelcased, Anda dapat mengganti RestSerializer
untuk mencapainya. Kami akan menggunakan perpustakaan utilitas lodash
:
import { RestSerializer } from 'miragejs'; import { camelCase, upperFirst } from 'lodash'; serializers: { application: RestSerializer.extend({ keyForAttribute(attr) { return upperFirst(camelCase(attr)); }, }), },
Ini harus menghasilkan JSON dalam bentuk:
{ "Rating": 5, "ProductCategory": "Fashion", "Price": "$1386", "Name": "Awesome Product 4", "Id": "5" }
Membungkus
Kau berhasil! Mudah-mudahan, Anda memiliki pemahaman yang lebih dalam tentang Mirage melalui artikel ini dan Anda juga telah melihat bagaimana memanfaatkan pabrik, perlengkapan, dan serializer akan memungkinkan Anda membuat lebih banyak tiruan API seperti produksi dengan Mirage.
- Bagian 1: Memahami Model dan Asosiasi Mirage JS
- Bagian 2: Memahami Pabrik, Perlengkapan, dan Serializer
- Bagian 3: Memahami Waktu, Respons, dan Passthrough
- Bagian 4: Menggunakan Mirage JS Dan Cypress Untuk Pengujian UI