Fermer

mai 29, 2020

Comprendre les usines, les luminaires et les sérialiseurs (partie 2)


À propos de l'auteur

Kelvin Omereshone est le directeur technique de Quru Lab . Kelvin était auparavant ingénieur front-end chez myPadi.ng. Il est le créateur de la communauté Nuxtjs Africa et très passionné…
En savoir plus sur
Kelvin

Dans cette deuxième partie de la série Mirage JS Deep Dive, nous examinerons les usines, les luminaires et les sérialiseurs de Mirage JS. Nous verrons comment ils permettent une simulation d'API rapide à l'aide de Mirage.

Dans l'article précédent de cette série, nous avons sous-étudié les modèles et les associations en ce qui concerne Mirage. J'ai expliqué que les modèles nous permettent de créer des données fictives dynamiques que Mirage pourrait servir à notre application lorsqu'elle fait une demande à nos points de terminaison fictifs. Dans cet article, nous examinerons trois autres fonctionnalités de Mirage qui permettent un mocking API encore plus rapide. Plongeons dedans!

Note : Je recommande fortement de lire mes deux premiers articles si vous ne voulez pas avoir une idée vraiment solide de ce qui serait discuté ici. Vous pouvez cependant toujours suivre et référencer les articles précédents si nécessaire.

Usines

Dans un article précédent j'ai expliqué comment Mirage JS est utilisé pour se moquer de l'API backend, supposons maintenant que nous nous moquons une ressource produit dans Mirage. Pour ce faire, nous créerions un gestionnaire d'itinéraires qui sera chargé d'intercepter les demandes vers un point de terminaison particulier, et dans ce cas, le point de terminaison est api / products . Le gestionnaire d'itinéraire que nous créons retournera tous les produits. Voici le code pour y parvenir dans Mirage:

 import {Server, Model} from 'miragejs';

nouveau serveur ({
    des modèles: {
      modèle du produit,
    },

   routes () {
        this.namespace = "api";
        this.get ('produits', (schéma, demande) => {
        renvoie schema.products.all ()
    })
   }
});
    },

La sortie de ce qui précède serait:

 {
  "produits": []
}

La sortie ci-dessus montre que la ressource produit est vide. Cela est toutefois prévu, car nous n'avons pas encore créé d'enregistrements.

Astuce de pro : Mirage fournit le raccourci nécessaire pour les points de terminaison API classiques. Ainsi, le gestionnaire d'itinéraire ci-dessus peut également être aussi court que: this.get ('/ products') .

Créons des enregistrements du modèle de produit à stocker dans la base de données Mirage en utilisant la méthode seeds sur notre instance Server :

 seeds (serveur) {
      server.create ('produit', {nom: 'Gemini Jacket'})
      server.create ('produit', {nom: 'Hansel Jeans'})
  },

La sortie:

 {
  "produits": [
    {
      "name": "Gemini Jacket",
      "id": "1"
    },
    {
      "name": "Hansel Jeans",
      "id": "2"
    }
  ]
}

Comme vous pouvez le voir ci-dessus, lorsque notre application frontale fait une demande à / api / products elle récupère une collection de produits telle que définie dans la méthode seed . [19659018] L'utilisation de la méthode seeds pour amorcer la base de données de Mirage est une étape de la création manuelle de chaque entrée en tant qu'objet. Cependant, il ne serait pas pratique de créer 1000 (ou un million) de nouveaux enregistrements de produits en utilisant le modèle ci-dessus. D'où la nécessité de usines .

Usines expliquées

Les usines sont un moyen plus rapide de créer de nouveaux enregistrements de base de données. Ils nous permettent de créer rapidement plusieurs enregistrements d'un modèle particulier avec des variations à stocker dans la base de données Mirage JS.

Les usines sont également des objets qui facilitent la génération de données d'aspect réaliste sans avoir à semer ces données individuellement. Les usines sont davantage des recettes ou des plans pour créer des enregistrements à partir de modèles.

Création d'une usine

Examinons une usine en créant une. L'usine que nous créerions sera utilisée comme modèle pour créer de nouveaux produits dans notre base de données Mirage JS.

 import {Factory} de 'miragejs'

nouveau serveur ({
    // y compris la définition du modèle pour une meilleure compréhension de ce qui se passe
    des modèles: {
        modèle du produit
    },
    des usines: {
        produit: Factory.extend ({})
    }
})

D'après ce qui précède, vous verriez que nous avons ajouté une propriété usines à notre instance Serveur et définissons une autre propriété à l'intérieur qui, par convention, est du même nom que le modèle que nous veulent créer une usine pour, dans ce cas, ce modèle est le produit . L'extrait ci-dessus illustre le modèle que vous suivriez lors de la création d'usines dans Mirage JS.

Bien que nous ayons une usine pour le modèle de produit nous ne lui avons vraiment pas ajouté de propriétés. Les propriétés d'une usine peuvent être des types simples comme chaînes booléens ou nombres ou fonctions qui renvoient des données dynamiques comme nous le verrions. dans l'implémentation complète de notre nouvelle usine de produits ci-dessous:

 import {Server, Model, Factory} from 'miragejs'

nouveau serveur ({
    des modèles: {
        modèle du produit
    },

   des usines: {
      produit: Factory.extend ({
        nom (i) {
          // i est l'index de l'enregistrement qui sera incrémenté automatiquement par Mirage JS
          return `Awesome Product $ {i}`; // Produit génial 1, produit génial 2, etc.
        },
        prix() {
          soit minPrice = 20;
          soit maxPrice = 2000;
          laissez randomPrice =
            Math.floor (Math.random () * (maxPrice - minPrice + 1)) + minPrice;
          return `$ $ {randomPrice}`;
        },
        Catégorie() {
          let categories = [
            'Electronics',
            'Computing',
            'Fashion',
            'Gaming',
            'Baby Products',
          ];
          laissez randomCategoryIndex = Math.floor (
            Math.random () * categories.length
          );
          laissez randomCategory = categories [randomCategoryIndex];
          return randomCategory;
        },
         évaluation() {
          laissez minRating = 0
          laissez maxRating = 5
          return Math.floor (Math.random () * (maxRating - minRating + 1)) + minRating;
        },
      }),
    },
})

Dans l'extrait de code ci-dessus, nous spécifions une logique javascript via Math.random pour créer des données dynamiques chaque fois que l'usine est utilisée pour créer un nouvel enregistrement de produit. Cela montre la force et la flexibilité des usines.

Créons un produit utilisant l'usine que nous avons définie ci-dessus. Pour ce faire, nous appelons server.create et passons le nom du modèle ( product ) sous forme de chaîne. Mirage créera ensuite un nouvel enregistrement d'un produit en utilisant l'usine de produits que nous avons définie. Le code dont vous avez besoin pour ce faire est le suivant:

 nouveau serveur ({
    graines (serveur) {
        server.create ("produit")
    }
})

Conseil de pro : Vous pouvez exécuter console.log (server.db.dump ()) pour voir les enregistrements dans la base de données de Mirage.

Un nouvel enregistrement semblable à celui ci-dessous a été créé et stocké dans la base de données Mirage.

 {
  "produits": [
    {
      "rating": 3,
      "category": "Computing",
      "price": "$739",
      "name": "Awesome Product 0",
      "id": "1"
    }
  ]
}

Redéfinition des usines

Nous pouvons remplacer une ou plusieurs des valeurs fournies par une usine en les transmettant explicitement de la manière suivante:

 server.create ("product", {name: "Yet Another Product", rating : 5, catégorie: "Mode"})

L'enregistrement résultant serait semblable à:

 {
  "produits": [
    {
      "rating": 5,
      "category": "Fashion",
      "price": "$782",
      "name": "Yet Another Product",
      "id": "1"
    }
  ]
}

createList

Avec une usine en place, nous pouvons utiliser une autre méthode sur l'objet serveur appelée createList . Cette méthode permet la création de plusieurs enregistrements d'un modèle particulier en transmettant le nom du modèle et le nombre d'enregistrements que vous souhaitez créer. Voici son utilisation:

 server.createList ("product", 10)

Ou

 server.createList ("produit", 1000)

Comme vous le constaterez, la méthode createList ci-dessus prend deux arguments: le nom du modèle sous forme de chaîne et un entier positif non nul représentant le nombre d'enregistrements à créer. Donc, à partir de ce qui précède, nous venons de créer 500 enregistrements de produits! Ce modèle est utile pour les tests d'interface utilisateur, comme vous le verrez dans un futur article de cette série.

Appareils

Dans les tests de logiciels, un appareil d'essai ou appareil est un état d'un ensemble ou d'une collection d'objets servant de référence pour l'exécution de tests. Le but principal d'un appareil est de s'assurer que l'environnement de test est bien connu afin de rendre les résultats reproductibles.

Mirage vous permet de créer des appareils et de les utiliser pour amorcer votre base de données avec les données initiales.

Note : Il est recommandé d'utiliser des usines 9 fois sur 10 car elles rendent vos mocks plus faciles à maintenir.

Création d'un appareil

Créons un appareil simple pour charger les données dans notre base de données:

 appareils: {
      produits: [
        { id: 1, name: 'T-shirts' },
        { id: 2, name: 'Work Jeans' },
      ],
  },

Les données ci-dessus sont automatiquement chargées dans la base de données en tant que données initiales de Mirage. Cependant, si vous avez défini une fonction semences, Mirage ignorerait votre appareil avec les hypothèses que vous vouliez qu'il soit remplacé et utiliserait plutôt des usines pour amorcer vos données.

Appareils en conjonction avec des usines

Mirage prend des dispositions pour vous d'utiliser des appareils aux côtés des usines. Vous pouvez y parvenir en appelant server.loadFixtures () . Par exemple:

 appareils: {
    produits: [
      { id: 1, name: "iPhone 7" },
      { id: 2, name: "Smart TV" },
      { id: 3, name: "Pressing Iron" },
    ],
  },

  graines (serveur) {
    // Permet aux luminaires et aux usines de vivre côte à côte
    server.loadFixtures ()

    server.create ("produit")
  },

Fichiers de fixtures

Idéalement, vous voudriez créer vos fixtures dans un fichier séparé de server.js et l'importer. Par exemple, vous pouvez créer un répertoire appelé fixtures et y créer products.js . Dans products.js ajoutez:

 //  /fixtures/products.js
export par défaut [
  { id: 1, name: 'iPhone 7' },
  { id: 2, name: 'Smart TV' },
  { id: 3, name: 'Pressing Iron' },
];

Puis dans server.js importez et utilisez le produit fixture comme ceci:

 importez des produits de './fixtures/products';
 agencements: {
    des produits,
 },

J'utilise le raccourci de la propriété ES6 afin d'affecter le tableau de produits importé à la propriété products de l'objet fixtures.

Il convient de mentionner que les luminaires seront ignorés par Mirage JS lors des tests sauf que vous lui dites explicitement de ne pas le faire en utilisant server.loadFixtures ()

Factories vs. Fixtures

À mon avis, vous devez vous abstenir d'utiliser des luminaires, sauf si vous avez un cas d'utilisation particulier où ils conviennent mieux que des usines. Les montages ont tendance à être plus verbeux tandis que les usines sont plus rapides et impliquent moins de frappes.

Sérialiseurs

Il est important de renvoyer une charge utile JSON qui est attendue à l'interface donc sérialiseurs .

Un sérialiseur est un objet qui est responsable de la transformation d'un ** modèle ** ou ** collection ** renvoyé par vos gestionnaires d'itinéraire en une charge utile JSON qui est formatée comme l'attend votre application frontale.

Mirage Docs

Prenons cet itinéraire gestionnaire par exemple:

 this.get ('products /: id', (schema, request) => {
        return schema.products.find (request.params.id);
      });

Un sérialiseur est chargé de transformer la réponse à quelque chose comme ceci:

 {
  "produit": {
    "note": 0,
    "catégorie": "Produits pour bébé",
    "prix": "654 $",
    "name": "Awesome Product 1",
    "id": "2"
  }
}

Sérialiseurs intégrés Mirage JS

Pour travailler avec les sérialiseurs Mirage JS, vous devez choisir le sérialiseur intégré pour commencer. Cette décision serait influencée par le type de JSON que votre backend enverrait éventuellement à votre application frontale. Mirage est fourni avec les sérialiseurs suivants:

  • JSONAPISerializer
    Ce sérialiseur suit le JSON: API spec .
  • ActiveModelSerializer
    Ce sérialiseur est destiné à imiter les API qui ressemblent aux API Rails construites avec active_model_serializer gem .
  • RestSerializer
    Le RestSerializer est Mirage JS "catch all" sérialiseur pour d'autres API courantes.

Serializer Definition

Pour définir une sérialisation , importez le sérialiseur approprié, par exemple RestSerializer de miragejs comme ceci:

 importez {Server, RestSerializer} de "miragejs"

Puis dans l'instance Server :

 nouveau serveur ({
  sérialiseurs: {
    application: RestSerializer,
  },
})

Le RestSerializer est utilisé par défaut par Mirage JS. Il est donc redondant de le définir explicitement. L'extrait ci-dessus est à titre d'exemple.

Voyons la sortie de JSONAPISerializer et ActiveModelSerializer sur le même gestionnaire d'itinéraire que nous avons défini ci-dessus

JSONAPISerializer

 import { Serveur, JSONAPISerializer} de "miragejs"
nouveau serveur ({
  sérialiseurs: {
    application: JSONAPISerializer,
  },
})

La sortie:

 {
  "Les données": {
    "type": "produits",
    "id": "2",
    "les attributs": {
      "note": 3,
      "catégorie": "Electronique",
      "prix": "1711 $",
      "name": "Awesome Product 1"
    }
  }
}

ActiveModelSerializer

Pour voir ActiveModelSerializer au travail, je modifierais la déclaration de catégorie dans l'usine de produits en:

 productCategory () {
          let categories = [
            'Electronics',
            'Computing',
            'Fashion',
            'Gaming',
            'Baby Products',
          ];
          laissez randomCategoryIndex = Math.floor (
            Math.random () * categories.length
          );
          laissez randomCategory = categories [randomCategoryIndex];
          return randomCategory;
        },

Tout ce que j'ai fait a été de changer le nom de la propriété en productCategory pour montrer comment le sérialiseur le gérerait.

Ensuite, nous définissons le ActiveModelSerializer sérialiseur comme ceci:

 importer {Server, ActiveModelSerializer} depuis "miragejs"
nouveau serveur ({
  sérialiseurs: {
    application: ActiveModelSerializer,
  },
})

Le sérialiseur transforme le JSON renvoyé comme:

 {
  "note": 2,
  "product_category": "Informatique",
  "prix": "64 $",
  "name": "Awesome Product 4",
  "id": "5"
}

Vous remarquerez que productCategory a été transformé en product_category qui est conforme à la gemme active_model_serializer de l'écosystème Ruby.

Personnalisation des sérialiseurs [19659002] Mirage offre la possibilité de personnaliser un sérialiseur. Supposons que votre application nécessite que vos noms d'attribut soient camelcasés, vous pouvez remplacer RestSerializer pour y parvenir. Nous utiliserions la bibliothèque d'utilitaires lodash :
 import {RestSerializer} de 'miragejs';
importer {camelCase, upperFirst} depuis 'lodash';
sérialiseurs: {
      application: RestSerializer.extend ({
        keyForAttribute (attr) {
          return upperFirst (camelCase (attr));
        },
      }),
    },

Cela devrait produire un JSON de la forme:

 {
      "Note": 5,
      "ProductCategory": "Fashion",
      "Prix": "1386 $",
      "Nom": "Awesome Product 4",
      "Id": "5"
    }

Conclusion

Vous avez réussi! J'espère que vous avez une meilleure compréhension de Mirage via cet article et que vous avez également vu comment l'utilisation d'usines, de montages et de sérialiseurs vous permettrait de créer des modèles d'API de type production avec Mirage. Recherchez la prochaine partie de cette série.

 Éditorial fracassant (ra, il)




Source link