Mirage JS Deep Dive: înțelegerea fabricilor, instalațiilor și serializatoarelor (Partea 2)
Publicat: 2022-03-10În articolul anterior al acestei serii, am studiat mai puțin Modelele și Asociațiile în ceea ce privește Mirage. Am explicat că Modelele ne permit să creăm date simulate dinamice pe care Mirage le-ar servi aplicației noastre atunci când face o solicitare către punctele noastre finale simulate. În acest articol, ne vom uita la alte trei caracteristici Mirage care permit o batjocură și mai rapidă a API-ului. Să ne scufundăm direct!
Notă : vă recomand să citiți primele două articole ale mele dacă nu trebuie să înțelegeți bine ceea ce ar fi discutat aici. Cu toate acestea, puteți urmări și face referire la articolele anterioare atunci când este necesar.
- Configurarea API Mocking cu Mirage JS și Vue
- Modele și asociații Mirage JS
Fabrici
Într-un articol anterior, am explicat cum este folosit Mirage JS pentru a bate joc de API-ul backend, acum să presupunem că ne batem joc de o resursă de produs în Mirage. Pentru a realiza acest lucru, vom crea un handler de rută care va fi responsabil pentru interceptarea cererilor către un anumit punct final și, în acest caz, punctul final este api/products
. Managerul de rută pe care îl creăm va returna toate produsele. Mai jos este codul pentru a realiza acest lucru în Mirage:
import { Server, Model } from 'miragejs'; new Server({ models: { product: Model, }, routes() { this.namespace = "api"; this.get('products', (schema, request) => { return schema.products.all() }) } }); },
Rezultatul celor de mai sus ar fi:
{ "products": [] }
Vedem din rezultatul de mai sus că resursa de produs este goală. Acest lucru este totuși de așteptat, deoarece nu am creat încă nicio înregistrare.
Sfat profesionist : Mirage oferă prescurtarea necesară pentru punctele finale API convenționale. Deci, handlerul de rută de mai sus ar putea fi, de asemenea, scurt ca: this.get('/products')
.
Să creăm înregistrări ale modelului de product
pentru a fi stocat în baza de date Mirage folosind metoda seeds
pe instanța noastră Server
:
seeds(server) { server.create('product', { name: 'Gemini Jacket' }) server.create('product', { name: 'Hansel Jeans' }) },
Ieșire:
{ "products": [ { "name": "Gemini Jacket", "id": "1" }, { "name": "Hansel Jeans", "id": "2" } ] }
După cum puteți vedea mai sus, atunci când aplicația noastră frontală face o solicitare către /api/products
, va primi înapoi o colecție de produse așa cum este definită în metoda seeds
.
Utilizarea metodei seeds
pentru a însămânța baza de date Mirage este un pas de la crearea manuală a fiecărei intrări ca obiect. Cu toate acestea, nu ar fi practic să creați 1000 (sau un milion) de înregistrări de produse noi folosind modelul de mai sus. De aici nevoia de fabrici .
Fabricile explicate
Fabricile sunt o modalitate mai rapidă de a crea noi înregistrări de baze de date. Ele ne permit să creăm rapid mai multe înregistrări ale unui anumit model, cu variații care să fie stocate în baza de date Mirage JS.
Fabricile sunt, de asemenea, obiecte care facilitează generarea de date cu aspect realist, fără a fi nevoie să sesăm aceste date individual. Fabricile sunt mai mult rețete sau planuri pentru crearea de înregistrări pe modele.
Crearea unei fabrici
Să examinăm o fabrică creând una. Fabrica pe care am crea-o va fi folosită ca model pentru crearea de noi produse în baza noastră de date Mirage JS.
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({}) } })
Din cele de mai sus, ați vedea că am adăugat o proprietate factories
la instanța noastră Server
și definim o altă proprietate în interiorul acesteia care, prin convenție, are același nume cu modelul pentru care dorim să creăm o fabrică, în acest caz, acel model este model de product
. Fragmentul de mai sus descrie modelul pe care l-ați urma atunci când creați fabrici în Mirage JS.
Deși avem o fabrică pentru modelul de product
, chiar nu i-am adăugat proprietăți. Proprietățile unei fabrici pot fi tipuri simple, cum ar fi șiruri , boolean sau numere , sau funcții care returnează date dinamice, așa cum am vedea în implementarea completă a noii noastre fabrici de produse de mai jos:
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; }, }), }, })
În fragmentul de cod de mai sus, specificăm o logică javascript prin Math.random
pentru a crea date dinamice de fiecare dată când fabrica este folosită pentru a crea o înregistrare nouă de produs. Aceasta arată puterea și flexibilitatea fabricilor.
Să creăm un produs utilizând fabrica pe care am definit-o mai sus. Pentru a face asta, apelăm server.create
și transmitem numele modelului ( product
) ca șir. Mirage va crea apoi o nouă înregistrare a unui produs utilizând fabrica de produse pe care am definit-o. Codul de care aveți nevoie pentru a face acest lucru este următorul:
new Server({ seeds(server) { server.create("product") } })
Sfat profesionist : Puteți rula console.log(server.db.dump())
pentru a vedea înregistrările din baza de date Mirage.
O nouă înregistrare similară cu cea de mai jos a fost creată și stocată în baza de date Mirage.
{ "products": [ { "rating": 3, "category": "Computing", "price": "$739", "name": "Awesome Product 0", "id": "1" } ] }
Preluarea fabricilor
Putem suprascrie unele sau mai multe dintre valorile furnizate de o fabrică, pasând-le în mod explicit astfel:
server.create("product", {name: "Yet Another Product", rating: 5, category: "Fashion" })
Înregistrarea rezultată ar fi similară cu:
{ "products": [ { "rating": 5, "category": "Fashion", "price": "$782", "name": "Yet Another Product", "id": "1" } ] }
createList
Cu o fabrică în loc, putem folosi o altă metodă pe obiectul server numit createList
. Această metodă permite crearea mai multor înregistrări ale unui anumit model prin introducerea numelui modelului și a numărului de înregistrări pe care doriți să le creați. Mai jos este modul de utilizare:
server.createList("product", 10)
Sau

server.createList("product", 1000)
După cum veți observa, metoda createList
de mai sus are două argumente: numele modelului ca șir și un întreg pozitiv diferit de zero reprezentând numărul de înregistrări de creat. Deci, din cele de mai sus, tocmai am creat 500 de înregistrări de produse! Acest model este util pentru testarea UI, așa cum veți vedea într-un articol viitor al acestei serii.
Fixare
În testarea software-ului, un dispozitiv sau un dispozitiv de testare este o stare a unui set sau a unei colecții de obiecte care servește drept linie de bază pentru rularea testelor. Scopul principal al unui dispozitiv este de a se asigura că mediul de testare este bine cunoscut pentru a face rezultatele repetabile.
Mirage vă permite să creați corpuri de iluminat și să le utilizați pentru a vă însămânța baza de date cu datele inițiale.
Notă : este recomandat să folosiți fabricile de 9 din 10 ori, deoarece acestea vă fac bateriile mai ușor de întreținut.
Crearea unui fix
Să creăm un dispozitiv simplu pentru a încărca date în baza noastră de date:
fixtures: { products: [ { id: 1, name: 'T-shirts' }, { id: 2, name: 'Work Jeans' }, ], },
Datele de mai sus sunt încărcate automat în baza de date ca date inițiale ale Mirage. Cu toate acestea, dacă aveți o funcție de semințe definită, Mirage ar ignora dispozitivul dvs. cu ipotezele pe care ați vrut ca acesta să fie suprascris și, în schimb, va folosi fabrici pentru a vă semăna datele.
Corpuri în legătură cu fabrici
Mirage vă asigură să utilizați Fixtures alături de Fabrici. Puteți realiza acest lucru apelând server.loadFixtures()
. De exemplu:
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") },
Fișiere de fixare
În mod ideal, ați dori să vă creați dispozitivele într-un fișier separat de server.js
și să-l importați. De exemplu, puteți crea un director numit fixtures
și în el puteți crea products.js
. În products.js
adăugați:
// <PROJECT-ROOT>/fixtures/products.js export default [ { id: 1, name: 'iPhone 7' }, { id: 2, name: 'Smart TV' }, { id: 3, name: 'Pressing Iron' }, ];
Apoi, în server.js
, importați și utilizați dispozitivul de fixare a produselor astfel:
import products from './fixtures/products'; fixtures: { products, },
Folosesc prescurtarea proprietății ES6 pentru a atribui matricea de produse importate proprietății products
a obiectului fixtures.
Este demn de menționat că instalațiile ar fi ignorate de Mirage JS în timpul testelor, cu excepția faptului că nu îi spuneți în mod explicit folosind server.loadFixtures()
Fabrici vs. Fixturi
În opinia mea, ar trebui să vă abțineți de la folosirea corpurilor de iluminat, cu excepția cazului de utilizare special în care acestea sunt mai potrivite decât fabricile. Fixările tind să fie mai detaliate, în timp ce fabricile sunt mai rapide și implică mai puține apăsări de taste.
Serializatoare
Este important să returnați o sarcină utilă JSON care este așteptată către frontend, deci serializatoare .
Un serializator este un obiect care este responsabil pentru transformarea unui **Model** sau **Colecție** care este returnat de la gestionatorii de rute într-o încărcare utilă JSON care este formatată așa cum se așteaptă aplicația dvs. frontală.
Mirage Docs
Să luăm de exemplu acest handler de rută:
this.get('products/:id', (schema, request) => { return schema.products.find(request.params.id); });
Un serializator este responsabil pentru transformarea răspunsului la ceva de genul acesta:
{ "product": { "rating": 0, "category": "Baby Products", "price": "$654", "name": "Awesome Product 1", "id": "2" } }
Serializatoare încorporate Mirage JS
Pentru a lucra cu serializatoarele Mirage JS, va trebui să alegeți cu ce serializator încorporat să începeți. Această decizie ar fi influențată de tipul de JSON pe care backend-ul tău l-ar trimite în cele din urmă către aplicația ta front-end. Mirage vine inclus cu următoarele serializatoare:
-
JSONAPISerializer
Acest serializator urmează specificațiile JSON:API. -
ActiveModelSerializer
Acest serializator este destinat să imite API-urile care seamănă cu API-urile Rails construite cu bijuteria active_model_serializer. -
RestSerializer
RestSerializer
este un serializator Mirage JS „catch all” pentru alte API-uri comune.
Definiția serializatorului
Pentru a defini o serializare, importați serializatorul adecvat, de exemplu RestSerializer
din miragejs
, astfel:
import { Server, RestSerializer } from "miragejs"
Apoi, în instanța Server
:
new Server({ serializers: { application: RestSerializer, }, })
RestSerializer
este utilizat implicit de Mirage JS. Deci, este redundant să-l setați în mod explicit. Fragmentul de mai sus are un scop exemplificativ.
Să vedem rezultatul ambelor JSONAPISerializer
și ActiveModelSerializer
pe același handler de rută așa cum am definit mai sus
JSONAPISerializator
import { Server, JSONAPISerializer } from "miragejs" new Server({ serializers: { application: JSONAPISerializer, }, })
Ieșire:
{ "data": { "type": "products", "id": "2", "attributes": { "rating": 3, "category": "Electronics", "price": "$1711", "name": "Awesome Product 1" } } }
ActiveModelSerializer
Pentru a vedea ActiveModelSerializer la lucru, aș modifica declarația de category
din fabrica de produse astfel:
productCategory() { let categories = [ 'Electronics', 'Computing', 'Fashion', 'Gaming', 'Baby Products', ]; let randomCategoryIndex = Math.floor( Math.random() * categories.length ); let randomCategory = categories[randomCategoryIndex]; return randomCategory; },
Tot ce am făcut a fost să schimb numele proprietății în productCategory
pentru a arăta cum o va gestiona serializatorul.
Apoi, definim serializatorul ActiveModelSerializer
astfel:
import { Server, ActiveModelSerializer } from "miragejs" new Server({ serializers: { application: ActiveModelSerializer, }, })
Serializatorul transformă JSON returnat ca:
{ "rating": 2, "product_category": "Computing", "price": "$64", "name": "Awesome Product 4", "id": "5" }
Veți observa că productCategory
a fost transformată în product_category
, care se conformează bijuteriei active_model_serializer a ecosistemului Ruby.
Personalizarea serializatoarelor
Mirage oferă posibilitatea de a personaliza un serializator. Să presupunem că aplicația dvs. necesită ca numele atributelor dvs. să fie încadrate în cămilă, puteți suprascrie RestSerializer
pentru a realiza acest lucru. Am folosi biblioteca de utilitate lodash
:
import { RestSerializer } from 'miragejs'; import { camelCase, upperFirst } from 'lodash'; serializers: { application: RestSerializer.extend({ keyForAttribute(attr) { return upperFirst(camelCase(attr)); }, }), },
Aceasta ar trebui să producă JSON de forma:
{ "Rating": 5, "ProductCategory": "Fashion", "Price": "$1386", "Name": "Awesome Product 4", "Id": "5" }
Încheierea
Ai făcut! Sperăm că aveți o înțelegere mai profundă a Mirage prin intermediul acestui articol și, de asemenea, ați văzut cum utilizarea fabricilor, instalațiilor și serializatoarelor vă va permite să creați mai multe modele API asemănătoare producției cu Mirage.
- Partea 1: Înțelegerea modelelor și asocierilor Mirage JS
- Partea 2: Înțelegerea fabricilor, instalațiilor și serializatoarelor
- Partea 3: Înțelegerea timpului, a răspunsului și a transmiterii
- Partea 4: Utilizarea Mirage JS și Cypress pentru testarea UI