Runtime
La validation runtime confirme si les décisions de domaine et d'API se comportent comme attendu sous une utilisation réelle de requêtes. C'est la couche où ton modèle passe de la conception à l'exécution — et où tu détectes les problèmes avant tes consommateurs.
Objectif du runtime
Le runtime répond à des questions pratiques tôt dans ton processus de développement :
- Les structures de champs sont-elles prévisibles et cohérentes ?
- Les résolutions de relations sont-elles cohérentes et correctement imbriquées ?
- Les hypothèses de pagination et de tri tiennent-elles avec les données importées ?
- Les expressions de filtre correspondent-elles au sous-ensemble correct d'enregistrements ?
- Les valeurs null sont-elles traitées comme tes consommateurs l'attendent ?
En validant ces comportements pendant la modélisation — pas après l'implémentation — tu élimines toute une catégorie d'erreurs d'intégration.


Panneau de requête runtime pour tests de comportement en direct.
Comment fonctionne le mock runtime
Le moteur de mock runtime est le cœur de Mockomat. Il accepte des requêtes GraphQL et les traduit en opérations MongoDB via une pipeline en quatre étapes :
1. GraphQL Request Parser
La chaîne de requête entrante est analysée en un arbre syntaxique abstrait (AST). Cette étape valide la syntaxe de la requête et extrait les champs demandés, les arguments et les sélections imbriquées.
2. Query Planner
L'AST est analysé conjointement avec les métadonnées de ton modèle (définitions d'entités, flags d'attributs, configurations de relations) pour créer un plan d'exécution. Le planner détermine :
- Quelles collections MongoDB interroger
- Quels champs projeter
- Quelles opérations de filtrage et de tri appliquer
- Quelles relations doivent être résolues
3. MongoDB Query Builder
Le plan d'exécution est traduit en pipeline d'agrégation MongoDB. Comme MongoDB stocke les données dans des collections plates (dénormalisées), le query builder simule les structures relationnelles :
- Étapes de lookup — assemblent les données liées entre collections
- Étapes de match — appliquent les expressions de filtre
- Étapes de sort — ordonnent les résultats selon les champs demandés
- Étapes de skip et limit — gèrent la pagination
4. Result Assembler
Les résultats bruts de MongoDB sont restructurés pour correspondre à la structure de réponse GraphQL attendue. Les relations imbriquées sont assemblées dans la hiérarchie parent-enfant correcte, et les noms de champs sont associés à leurs équivalents GraphQL.
Cette pipeline s'exécute à chaque requête. Ce que tu vois en prévisualisation est exactement ce que les consommateurs externes recevront du même endpoint.


Pipeline runtime en quatre étapes : Parse → Plan → Build → Assemble.
Exemples de requêtes
Toutes les requêtes utilisent le même endpoint, avec une clé API du projet (les projets invités utilisent leur token de partage — voir Intégrateurs) :
POST /mock/{slug}/graphql
Authorization: Bearer mck_your_api_keyLe champ racine est le nom d'une opération de la conception API. Une requête de liste sélectionne ses enregistrements dans items et peut y ajouter total, page et pageSize ; une requête de détail sélectionne directement les champs. La réponse contient chaque attribut mappé de la table et ses relations — la sélection ne la restreint pas.
Requête de liste
Récupérer une collection paginée d'enregistrements :
query {
products(page: 1, pageSize: 20) {
items {
id
name
price
category {
id
name
}
}
total
page
pageSize
}
}Requête de détail
Récupérer un seul enregistrement par son identifiant :
query {
product(id: "abc-123") {
id
name
price
description
category {
id
name
}
}
}Requête avec filtrage
Passe les paramètres que l'opération définit dans la conception API — ici minPrice (sur price, gte) et maxPrice (sur price, lte) :
query {
products(minPrice: 10, maxPrice: 50, pageSize: 10) {
items {
id
name
price
}
total
}
}Requête avec tri
Trie les résultats avec sortField (un nom d'attribut) et sortDirection :
query {
products(sortField: "price", sortDirection: DESC, pageSize: 10) {
items {
id
name
price
}
total
}
}Requête avec relations imbriquées
Les relations de la table reviennent imbriquées, sur un niveau :
query {
customers(pageSize: 5) {
items {
id
firstName
lastName
orders {
id
totalAmount
createdAt
}
}
total
}
}Filtrage en détail
Les filtres appartiennent à l'opération : tu les définis dans la conception API et le runtime les applique à chaque requête. Les filtres de portée sont des conditions fixes de l'opération ; les paramètres sont des arguments envoyés par l'appelant — chacun lié à un attribut et à un opérateur, éventuellement obligatoire ou avec une valeur par défaut.
Opérateurs disponibles
| Opérateur | Description | Fonctionne avec |
|---|---|---|
eq | Égal | Tous les types |
neq | Différent | Tous les types |
gt / gte | Supérieur à / supérieur ou égal | Nombres, dates |
lt / lte | Inférieur à / inférieur ou égal | Nombres, dates |
in | L'une des valeurs d'une liste | Tous les types |
like | Contient (sans tenir compte de la casse) | Chaînes |
notIn | Aucune des valeurs d'une liste (filtres de portée uniquement) | Tous les types |
isNull / isNotNull | Est null / n'est pas null (filtres de portée uniquement) | Tous les types |
Combiner les filtres
Tous les filtres de portée et paramètres d'une opération se combinent avec AND — il n'y a ni OR ni imbrication au moment de la requête. Passe les valeurs des paramètres en ligne ou comme variables GraphQL :
query ProductsInRange($min: Float, $max: Float) {
products(minPrice: $min, maxPrice: $max, pageSize: 20) {
items {
id
name
price
}
total
}
}Avec les variables { "min": 10, "max": 50 }, cela retourne les produits dont le prix va de 10 à 50.
Validation des paramètres
Un argument que l'opération ne définit pas est refusé avec BAD_USER_INPUT, tout comme un paramètre obligatoire manquant sans valeur par défaut. Les opérations sans paramètres ignorent les arguments inconnus. Définis les paramètres dans la conception API.
Recherche
searchTerm recherche sans tenir compte de la casse dans tous les attributs marqués comme recherchables (jusqu'à 64 caractères) :
query {
products(searchTerm: "oak", pageSize: 10) {
items {
id
name
}
total
}
}Pagination
Mockomat utilise la pagination par pages :
| Paramètre | Description | Défaut |
|---|---|---|
page | Numéro de page, à partir de 1 | 1 |
pageSize | Enregistrements par page, 100 au maximum | Taille de page par défaut de l'opération (25 sauf modification) |
Une requête paginée typique :
query {
products(page: 3, pageSize: 20) {
items {
id
name
price
}
total
page
pageSize
}
}Cela retourne les enregistrements 41 à 60. total compte tous les enregistrements correspondants : la dernière page est donc total / pageSize, arrondi au supérieur.
Tri
Trie avec sortField (un nom d'attribut) et sortDirection :
| Direction | Signification |
|---|---|
ASC | Croissant (A→Z, 0→9, plus ancien→plus récent) |
DESC | Décroissant (Z→A, 9→0, plus récent→plus ancien) |
Un seul champ de tri peut être appliqué par requête. Sans sortField, le tri par défaut de l'opération s'applique ; si elle n'en a pas, les résultats arrivent dans l'ordre de stockage.
Traversée des relations
L'une des fonctionnalités les plus puissantes du runtime est sa capacité à simuler des données relationnelles à partir de collections MongoDB plates.
Comment ça fonctionne
MongoDB stocke les données dans des collections dénormalisées — chaque enregistrement est un document plat sans jointures de clé étrangère. Le runtime simule les structures relationnelles en :
- Lisant la définition de relation depuis ton modèle (entité source, entité cible, cardinalité).
- Construisant des étapes de lookup dans la pipeline d'agrégation MongoDB qui joignent les collections liées.
- Assemblant les résultats imbriqués correspondant à la structure de réponse GraphQL.
Cela signifie que tes requêtes GraphQL se comportent comme si elles s'exécutaient contre une base de données entièrement relationnelle, bien que le stockage sous-jacent soit basé sur les documents.
Ce qu'il faut valider
Lors de la vérification de la traversée des relations :
- Relations 1:1 devraient retourner un seul objet imbriqué (ou null s'il n'y a pas de correspondance).
- Relations 1:n devraient retourner un tableau d'objets imbriqués.
- Relations vides devraient retourner un tableau vide
[], pas null. - Les relations imbriquées se résolvent sur un niveau : un enregistrement lié porte ses propres attributs, pas ses relations (Customer → Order fonctionne ; les lignes de la commande ne sont pas incluses). Chaque parent reçoit au plus 50 enregistrements liés.
Liste de contrôle du comportement des requêtes
Pour chaque entité clé de ton modèle, valide :
- Stabilité des requêtes de liste — la même requête retourne-t-elle une structure cohérente lors d'appels répétés ?
- Cohérence des éléments individuels — une requête de détail retourne-t-elle tous les champs attendus ?
- Comportement des champs null et manquants — les champs optionnels sont-ils correctement représentés comme null ?
- Traversée des relations — les objets imbriqués se résolvent-ils avec la cardinalité correcte ?
- Précision des filtres — les expressions de filtre correspondent-elles au sous-ensemble attendu ?
- Exactitude du tri — le tri produit-il un ordre prévisible et stable ?
- Limites de pagination —
pageetpageSizeproduisent-ils des tranches de page propres sans doublons ?


Validation du comportement de filtrage, tri et pagination.
Inspection et débogage runtime
Lorsque le comportement semble incorrect, inspecte dans cet ordre :
1. Vérifier les définitions de tables et d'attributs
La cause la plus courante de comportement inattendu est un attribut mal configuré :
- Le type de champ est-il correct ? (Un prix stocké comme
stringne sera pas trié numériquement.) - Pour la recherche : le champ est-il marqué comme recherchable ?
- Pour le tri :
sortFieldest-il le nom d'un attribut lié à une colonne de données ? - Le champ a-t-il une association configurée ?
2. Vérifier les métadonnées d'endpoint et de requête
Vérifie que la requête est correctement configurée dans la vue de conception API :
- La requête est-elle activée ?
- Le nom et les paramètres de la requête sont-ils corrects ?
- La configuration de pagination est-elle appropriée ?
3. Vérifier l'état de l'association source
Si les champs retournent null ou des valeurs inattendues :
- Le type d'association est-il correct (Source de données ou Constante) ?
- Pour les associations Source de données, l'attribut est-il lié à la bonne colonne des données importées, et cette colonne contient-elle des valeurs pour ces enregistrements ?
- Les valeurs constantes apparaissent sur chaque ligne, aussi bien sur les lignes de données importées que sur les lignes composées à partir de pools de valeurs.
- Pour les associations calculées, le runtime n'évalue pas les expressions : un champ calculé ne fait donc pas partie de la réponse.
4. Vérifier les politiques de relations
Si les données imbriquées sont manquantes ou incorrectes :
- La direction de la relation est-elle correcte (source → cible) ?
- La cardinalité correspond-elle (1:1 vs 1:n) ?
- L'entité cible existe-t-elle et a-t-elle des données associées ?
- Les colonnes de jointure sont-elles correctement spécifiées ?
Problèmes courants et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| Réponse vide | La table n'est pas liée à des données importées (NOT_READY) | Lier la table aux données importées dans le panneau Mappings du board |
| Champs retournant null | Aucune association configurée | Lier l'attribut à une colonne des données importées (association Source de données) |
| Relation imbriquée vide | Relation mal configurée | Vérifier la direction, l'entité cible et les colonnes de jointure |
| Le tri ne fonctionne pas | sortField n'est pas un attribut mappé | Utiliser le nom d'un attribut mappé |
| Le filtre retourne tout | L'opération ne définit aucun paramètre pour cet argument | Ajouter le paramètre dans la conception API |
| Types de données incorrects | Discordance de type d'association | Vérifier que l'association produit le type attendu |
| La pagination saute des éléments | pageSize a changé entre les requêtes | Garder pageSize constant et avancer page de 1 |


Flux d'inspection runtime et points de contrôle de débogage.
Validation avant export
Le runtime devrait confirmer la disponibilité avant de passer à la génération de code backend. Un modèle qui passe la validation runtime a significativement plus de chances de produire un backend généré propre et fonctionnel.
Critères de disponibilité
Avant l'export, confirme que :
- Les champs obligatoires sont stables — tous les attributs obligatoires ont des valeurs cohérentes et non-null.
- La surface d'opérations est intentionnelle — seules les requêtes que tu souhaites exposer sont activées.
- Le comportement des relations est explicable — chaque requête imbriquée se résout correctement et la cardinalité correspond à tes règles métier.
- Le comportement des filtres et du tri est prévisible — les consommateurs peuvent compter sur le fonctionnement documenté de ces opérations.
- Aucune indication non résolue — la prévisualisation n'affiche aucun avertissement sur des attributs non associés ou une configuration manquante.
Workflow de validation pré-export
- Exécuter des requêtes de liste pour chaque entité — vérifier la structure et la qualité des données.
- Exécuter des requêtes de détail pour les entités clés — vérifier la complétude des champs.
- Tester tous les filtres configurés — vérifier le sous-ensemble correct.
- Tester le tri sur les attributs selon lesquels tes consommateurs trient — vérifier l'ordre.
- Tester les limites de pagination — vérifier les transitions de page propres.
- Tester les requêtes de relations imbriquées — vérifier l'assemblage correct à chaque niveau.


Résumé de validation runtime pré-export.