订阅以接收新文章的通知:

Amélioration des tests dans Workers via Vitest et workerd

2024/03/15

16 分钟阅读时间

Aujourd'hui, nous sommes heureux d'annoncer une nouvelle intégration de Vitest dans Workers, qui vous permet d'écrire des tests unitaires et d'intégration par l'intermédiaire du célèbre système de test Vitest et des les exécuter directement dans notre runtime workerd !

Cette intégration vous offre la capacité de tester tous les paramètres de votre instance Workers !

Pour la première fois, vous pouvez écrire des tests unitaires qui s'exécutent dans le même runtime que Cloudflare Workers en production. Ceci vous offre l'assurance que le comportement de votre instance Workers pendant les tests restera inchangé lorsqu'elle sera déployée en production. Pour les tests d'intégration, vous pouvez maintenant écrire des tests pour Workers qui sont déclenchés par des Cron Triggers, en plus des événements  fetch() traditionnels. Vous pouvez également tester plus facilement des applications complexes qui interagissent avec KV, R2, D1, Queues, Service Bindings et d'autres produits Cloudflare.

Pour tous vos tests, vous avez accès aux fonctionnalités de Vitest telles que les fonctions snapshot, mock, timer et spy.

Outre l'augmentation du nombre de tests et de fonctionnalités disponibles, vous remarquerez également d'autres améliorations apportées à l'expérience des développeurs, telles que le rechargement à chaud de modules, l'activation par défaut du mode de surveillance et le stockage isolé par test. Ainsi, au fur et à mesure que vous développez et modifiez vos tests, ils sont automatiquement exécutés une nouvelle fois, sans nécessiter le redémarrage de votre programme d'exécution de tests.

Commencez à tester Workers avec Vitest

La façon la plus simple de commencer à tester votre Workers via Vitest est de créer un nouveau projet Workers à l'aide de notre outil create-cloudflare :

npm create cloudflare@latest hello-world -- --type=hello-world

Lorsque vous exécutez cette commande, un nouveau projet est créé et l'intégration de Workers dans Vitest déjà configurée. Un exemple de test unitaire et de test d'intégration est également inclus.

Instructions d'installation et de configuration manuelles

Si vous préférez installer et configurer manuellement l'intégration de Workers dans Vitest, commencez par installer @cloudflare/vitest-pool-workers depuis npm :

$ npm install --save-dev @cloudflare/vitest-pool-workers

@cloudflare/vitest-pool-workers comporte une dépendance de pairs (« peer dependency ») vis-à-vis d'une version spécifique de vitest. Les versions modernes de npm l'installent automatiquement, mais nous vous recommandons de l'installer également de manière explicite. Référez-vous au guide de démarrage pour connaître la version actuellement prise en charge. Si vous utilisez TypeScript, ajoutez @cloudflare/vitest-pool-workers à la section types de votre fichier tsconfig.json pour obtenir les types du module cloudflare:test :

{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler",
    "lib": ["esnext"],
    "types": [
      "@cloudflare/workers-types/experimental",
      "@cloudflare/vitest-pool-workers"
    ]
  }
}

Ensuite, activez le pool dans votre fichier de configuration Vitest :

// vitest.config.js
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";

export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: "./wrangler.toml" },
      },
    },
  },
});

Définissez ensuite une date de compatibilité ultérieure à "2022-10-31", puis activez l'indicateur de compatibilité nodejs_compat dans votre fichier wrangler.toml:

# wrangler.toml
main = "src/index.ts"
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]

Tester toutes les données exportées depuis une instance Workers

Avec la nouvelle intégration de Workers dans Vitest, vous pouvez tester toutes les données exportées depuis votre instance Workers sous forme de tests unitaires et de tests d'intégration. Dans ces tests, vous pouvez également tester des ressources connectées telles que R2, KV et Durable Objects, ainsi que des applications impliquant plusieurs instances Workers.

Écrire des tests unitaires

Dans le contexte de Workers, un test unitaire importe et appelle directement des fonctions depuis votre instance Workers, puis il effectue des assertions sur les valeurs qu'elles renvoient. Supposons que votre instance Workers se présente comme ceci :

export function add(a, b) {
  return a + b;
}

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const a = parseInt(url.searchParams.get("a"));
    const b = parseInt(url.searchParams.get("b"));
    return new Response(add(a, b));
  }
}

Après avoir configuré et installé l'intégration de Workers dans Vitest, vous pouvez tester cette instance Workers en créant un nouveau fichier de test appelé index.spec.js avec le code suivant :

import { env, createExecutionContext, waitOnExecutionContext, } from "cloudflare:test";
import { describe, it, expect } from "vitest";
import { add }, worker from "./src";

describe("Hello World worker", () => {
  it(“adds two numbers”, async () => {
    expect(add(2,3).toBe(5);
  });
  it("sends request (unit style)", async () => {
    const request = new Request("http://example.com/?a=3&b=4");
    const ctx = createExecutionContext();
    const response = await worker.fetch(request, env, ctx);
    await waitOnExecutionContext(ctx);
    expect(await response.text()).toMatchInlineSnapshot(`"7"`);
  });
});

L'intégration de Workers dans Vitest vous permet d'écrire des tests unitaires comme ceux-ci pour n'importe laquelle de vos instances Workers.

Écrire des tests d'intégration

Si les tests unitaires sont parfaits pour tester des parties individuelles de votre application, les tests d'intégration évaluent plusieurs unités de fonctionnalités, en assurant que l'exécution des flux de travail et des fonctionnalités est conforme aux attentes. Ces tests sont généralement plus complexes que les tests unitaires, mais ils vous offrent l'assurance que votre application fonctionne comme prévu. Dans le contexte de Workers, un test d'intégration transmet des requêtes HTTP à votre instance Workers et émet des assertions en fonction des réponses HTTP.

L'intégration de Workers dans Vitest vous permet d'exécuter des tests d'intégration en important SELF depuis le nouvel utilitaire cloudflare:test , comme ceci :

// test/index.spec.ts
import { SELF } from "cloudflare:test";
import { it, expect } from "vitest";
import "../src";

// an integration test using SELF
it("sends request (integration style)", async () => {
   const response = await SELF.fetch("http://example.com/?a=3&b=4");
   expect(await response.text()).toMatchInlineSnapshot(`"7"`);
});

Lorsque vous utilisez SELF pour les tests d'intégration, votre code Workers s'exécute dans le même contexte que le programme d'exécution de tests. Cela signifie que vous pouvez utiliser des simulations (mock) pour contrôler votre instance Workers.

Tester différents scénarios

Que vous écriviez des tests unitaires ou des tests d'intégration, si votre application utilise les produits de la plateforme pour développeurs de Cloudflare (par exemple, KV, R2, D1, Queues ou Durable Objects), vous pouvez réaliser des tests sur ceux-ci. Pour le démontrer, nous avons créé une série d'exemples qui vous aideront à effectuer vos premiers tests.

Meilleure expérience de test = meilleurs tests

Disposer de meilleurs outils de test vous permet de tester plus facilement vos projets dès le lancement, ce qui se traduit par une qualité globale et une expérience meilleures pour vos utilisateurs finaux. L'intégration de Workers dans Vitest propose en effet une meilleure expérience, non seulement en offrant une expérience améliorée aux développeurs, mais également en facilitant l'exécution de tests sur l'ensemble de l'application.

La suite de cet article se concentrera sur l'approche que nous avons utilisée pour créer cette nouvelle intégration de test, en examinant les rouages internes du fonctionnement de Vitest, les problèmes que nous avons rencontrés en essayant d'intégrer un système dans notre runtime, et enfin, comment nous avons résolu ces problèmes et l'amélioration qu'a eu cette démarche sur l'expérience des développeurs.

Comment fonctionne traditionnellement Vitest

Lorsque vous démarrez l'interface de ligne de commande de Vitest, celle-ci commence par collecter et séquencer tous vos fichiers de test. Par défaut, Vitest utilise un pool de « threads » qui génère les threads Node.js de Workers afin d'isoler et d'exécuter des tests en parallèle. Chaque thread reçoit un fichier de test à exécuter et demande et évalue le code dynamiquement, selon les besoins. Lorsque le programme d'exécution de tests importe un module, il transmet une requête à l'instance « vite-node server » de l'hôte, qui renvoie soit du code JavaScript brut transformé par Vite, soit un chemin d'accès au module externe. S'il renvoie du code brut, celui-ci est exécuté avec la fonction node:vm runInThisContext(). S'il renvoie un chemin de module, celui-ci est importé avec la fonction dynamique import(). La transformation du code utilisateur avec Vite permet le rechargement à chaud de modules (HMR, « Hot Module Reloading ») ; en cas de modification d'un module, il est invalidé dans le cache du module, et une nouvelle version est renvoyée lors de l'importation suivante.

overview of Vitest’s architecture using Miniflare v2’s environments

Miniflare est un simulateur entièrement local pour la plateforme pour développeurs de Cloudflare. Miniflare v2 fournissait un environnement personnalisé pour Vitest, vous permettant d'exécuter vos tests dans le sandbox Workers. Vous pouviez ainsi importer et appeler, pendant vos tests, n'importe quelle fonction avec des API runtime de Workers. Vous n'étiez pas contraint de vous limiter à des tests d'intégration qui transmettaient et recevaient simplement des requêtes HTTP. En outre, cet environnement proposait un stockage isolé par test, annulant automatiquement toutes les modifications apportées à la fin de chaque test. Dans Miniflare v2, cet environnement était relativement simple à déployer. Nous avions déjà redéployé les API runtime de Workers dans un environnement Node.js et, à l'aide des API de Vitest, nous pouvions les injecter dans la portée globale du programme d'exécution de tests.

En revanche, Miniflare v3 exécute votre code Workers dans le même runtime workerd utilisé par Cloudflare en production. L'exécution de tests directement dans workerd présentait un défi – workerd s'exécute dans son propre processus, distinct du thread worker Node.js, et il n'est pas possible de référencer des classes JavaScript au-delà d'une limite de processus.

problem with Miniflare v3, the runtime APIs are defined in a separate process to the test environments, and JavaScript objects cannot cross process boundaries

Résoudre le problème des pools personnalisés

À la place, nous utilisons les pools personnalisés de Vitest pour exécuter le programme d'exécution de tests dans les instances de Cloudflare Workers qui s'exécutent localement avec workerd. Un pool reçoit les fichiers de test à exécuter et décide comment les exécuter. L'exécution du programme d'exécution dans workerdpermettent d'assurer aux tests un accès direct aux API runtime de Workers, puisque celles-si s'exécutent dans une instance Workers. Les instances WebSocket sont utilisées pour transmettre et recevoir des messages RPC sérialisables entre l'hôte Node.js et le processus workerd. Notez que nous exécutons ici exactement le même code de programme d'exécution de test, conçu à l'origine pour Node-context dans une instance Workers. Cela signifie que notre instance Workers doit fournir les modules intégrés de Node, la prise en charge de l'évaluation dynamique du code, ainsi que le chargement de modules arbitraires depuis le disque avec le comportement Node-resolution. L'indicateur de compatibilité nodejs_compat fournit une prise en charge pour certains des modules intégrés de Node, mais il ne résout pas nos autres problèmes. Pour cela, nous avons dû faire preuve de créativité...

our solution for Miniflare v3, make the tests run in workerd, and use WebSockets for communication

Évaluation dynamique du code

Pour des raisons de sécurité, le runtime de Cloudflare Workers ne permet pas l'évaluation dynamique du code via eval() ou new Function(). Il exige également que tous les modules soient définis à l'avance, avant le démarrage de l'exécution. Le programme d'exécution de tests ne sait pas quel code exécuter jusqu'à ce que nous commencions à exécuter les tests ; aussi, si nous ne levons pas ces restrictions, nous n'avons aucun moyen d'exécuter le code JavaScript brut transformé par Vite, ni d'importer des modules arbitraires depuis le disque. Heureusement, le code qui n'est destiné qu'à être exécuté localement (les tests, par exemple) bénéficie d'un modèle de sécurité beaucoup plus tolérant que le code déployé. Pour prendre en charge les tests locaux et d'autres scénarios d'utilisation spécifiques au développement, à l'image de la nouvelle API Vite Runtime, nous avons ajouté des « liaisons unsafe-eval » et des « services module-fallback » à workerd.

Les liaisons unsafe-eval fournissent un accès local à la fonction eval() et aux constructeurs new Function()/new AsyncFunction()/new WebAssembly.Module(). En exposant ces fonctions par le biais d'une liaison, nous gardons le contrôle sur le code qui a accès à celles-ci.

// Type signature for unsafe-eval bindings
interface UnsafeEval {
  eval(script: string, name?: string): unknown;
  newFunction(script: string, name?: string, ...args: string[]): Function;
  newAsyncFunction(script: string, name?: string, ...args: string[]): AsyncFunction;
  newWasmModule(src: BufferSource): WebAssembly.Module;
}

Grâce à la méthode de liaison unsafe-eval eval() , nous avons pu mettre en œuvre un polyfill pour la fonctionvm.runInThisContext() requise. Nous pourrions également mettre en œuvre le chargement de modules arbitraires depuis le disque avec des liaisons unsafe-eval ; toutefois, cela nous contraindrait à recréer le système de résolution de modules de workerd en langage JavaScript. Au lieu de cela, nous permettons la configuration des instances Workers avec des services module-fallback. Si cette option est activée, les importations qui ne peuvent pas être résolues par workerd deviennent des requêtes HTTP transmises au service de secours. Ces requêtes incluent le spécificateur et le référent, et indiquent s'il s'agit d'une fonction import ou require. Le service peut répondre avec une définition de module ou une redirection vers un autre emplacement si l'emplacement résolu ne correspond pas au spécificateur. Les requêtes provenant de fonctions require synchrones bloqueront le thread principal jusqu'à la résolution du module. Le service de secours du pool Vitest de Workers implémente une résolution de type Node avec une interopérabilité de type Node entre les modules CommonJS et ES.

Utilisation d'instances Durable Objects en tant que programmes d'exécution de tests

Maintenant que nous pouvons exécuter et importer du code arbitraire, l'étape suivante consiste à exécuter le thread Workers de Vitest dans workerd. Chaque requête entrante possède un contexte de requête propre. Pour améliorer les performances globales, les objets E/S tels que les flux, les corps de requête/de réponse et les instances WebSocket créées dans un contexte de requête déterminé ne peuvent pas être utilisés depuis un autre contexte de requête. Par conséquent, si nous voulons utiliser une instance WebSocket pour RPC entre le pool et nos processus workerd , nous devons nous assurer que l'instance WebSocket est utilisée depuis un contexte de requête seulement. Pour coordonner cela, nous définissons un singleton Durable Objects, qui acceptera la connexion RPC et depuis lequel les tests seront exécutés. Les fonctions utilisant RPC, telles que la résolution de modules, les rapports de résultats et la journalisation de la console, utiliseront toujours ce singleton. Nous utilisons le système « Magic Proxy » de Miniflare pour obtenir une référence au stub du singleton dans Node.js et transmettre directement à celui-ci une requête de mise à niveau via WebSocket. Après avoir ajouté quelques polyfills Node.js supplémentaires, ainsi qu'un module de base cloudflare:test pour fournir un accès aux liaisons et une fonction pour créer des informations ExecutionContext, nous sommes en mesure d'écrire des tests unitaires basiques dans Workers ! 🎉

architecture of the Workers Vitest Pool

Tests d'intégration avec rechargement à chaud des modules

En plus des tests unitaires, nous prenons en charge les tests d'intégration avec une liaison spéciale de service SELF dans le module cloudflare:test. Celle-ci renvoie vers un handler spécial export default { fetch(...) {...} } , qui utilise Vite pour importer le module main de votre instance Workers.

L'utilisation du pipeline de transformation de Vite permet à votre handler de bénéficier gratuitement de la fonction de rechargement à chaud des modules (HMR, Hot Module Reloading) ! Lorsque le code est mis à jour, le cache du module est invalidé, les tests sont exécutés une nouvelle fois et les requêtes suivantes s'exécutent avec le nouveau code. La même approche consistant à intégrer les handlers de code utilisateur s'applique également aux instances Durable Objects, offrant les mêmes avantages en termes de HMR.

Les tests d'intégration peuvent être écrits en appelant SELF.fetch(), qui transmettra un événement fetch() à votre code utilisateur dans la même portée globale que votre test, toutefois, dans un contexte de requête différent. Cela signifie que les simulations (mock) globales s'appliquent à l'exécution de votre instance Workers, tout comme les restrictions de durée de vie du contexte de requêtes. En particulier, si vous oubliez d'appeler ctx.waitUntil(), vous verrez s'afficher un message d'erreur correspondant. Ce ne serait pas le cas si vous appeliez le handler de votre instance Workers directement dans un test unitaire, car l'exécution se déroulerait alors dans le contexte de la requête Durable Objects du singleton du programme d'exécution de tests, dont la durée de vie est automatiquement prolongée.

// test/index.spec.ts
import { SELF } from "cloudflare:test";
import { it, expect } from "vitest";
import "../src/index";

it("sends request", async () => {
   const response = await SELF.fetch("https://example.com");
   expect(await response.text()).toMatchInlineSnapshot(`"body"`);
});

Stockage isolé par test

La plupart des applications Workers comporteront au moins une liaison avec un service de stockage Cloudflare tel que KV, R2 ou D1. Idéalement, les tests devraient être autonomes et pouvoir être exécutés dans n'importe quel ordre ou même seuls. Pour que cela soit possible, les écritures dans le stockage doivent être annulées à la fin de chaque test, afin que les lectures effectuées par d'autres tests ne soient pas affectées. Bien qu'il soit possible de le faire manuellement, il peut être difficile d'assurer le suivi de toutes les écritures et de les annuler dans l'ordre correct. Prenons par exemple les deux fonctions suivantes :

// helpers.ts
interface Env {
  NAMESPACE: KVNamespace;
}
// Get the current list stored in a KV namespace
export async function get(env: Env, key: string): Promise<string[]> {
  return await env.NAMESPACE.get(key, "json") ?? [];
}
// Add an item to the end of the list
export async function append(env: Env, key: string, item: string) {
  const value = await get(env, key);
  value.push(item);
  await env.NAMESPACE.put(key, JSON.stringify(value));
}

Si nous voulions tester ces fonctions, nous pourrions écrire du code semblable à celui présenté ci-dessous. Notez que nous devons assurer le suivi de toutes les clés sur lesquelles nous pourrions écrire et restaurer leurs valeurs à la fin des tests, même si ces tests échouent.

// helpers.spec.ts
import { env } from "cloudflare:test";
import { beforeAll, beforeEach, afterEach, it, expect } from "vitest";
import { get, append } from "./helpers";

let startingList1: string | null;
let startingList2: string | null;
beforeEach(async () => {
  // Store values before each test
  startingList1 = await env.NAMESPACE.get("list 1");
  startingList2 = await env.NAMESPACE.get("list 2");
});
afterEach(async () => {
  // Restore starting values after each test
  if (startingList1 === null) {
    await env.NAMESPACE.delete("list 1");
  } else {
    await env.NAMESPACE.put("list 1", startingList1);
  }
  if (startingList2 === null) {
    await env.NAMESPACE.delete("list 2");
  } else {
    await env.NAMESPACE.put("list 2", startingList2);
  }
});

beforeAll(async () => {
  await append(env, "list 1", "one");
});

it("appends to one list", async () => {
  await append(env, "list 1", "two");
  expect(await get(env, "list 1")).toStrictEqual(["one", "two"]);
});

it("appends to two lists", async () => {
  await append(env, "list 1", "three");
  await append(env, "list 2", "four");
  expect(await get(env, "list 1")).toStrictEqual(["one", "three"]);
  expect(await get(env, "list 2")).toStrictEqual(["four"]);
});

Cela s'avère peu plus facile avec le hook onTestFinished(), que nous avons récemment inauguré, mais vous devez toujours vous rappeler sur quelles clés une écriture a été effectuée ou énumérer celles-ci au début/à la fin des tests. Vous devez également gérer cette contrainte pour KV, R2, Durable Objects, les caches et tout autre service de stockage que vous avez utilisé. Idéalement, le système de test devrait gérer tout cela à votre place.

C'est exactement ce que fait le pool Vitest de Workers avec l'option isolatedStorage , qui est activée par défaut. Toutes les écritures dans le stockage effectuées pendant un test sont automatiquement annulées à la fin du test. Pour prendre en charge le seeding des données dans les hooks beforeAll() , y compris celles dans les blocs describe() imbriqués, une pile est utilisée. Avant chaque suite ou test, une nouvelle trame est placée dans la pile de stockage. Toutes les écritures effectuées par le test ou les crochets beforeEach()/afterEach() associés sont écrites dans la trame. Après chaque suite ou test, la trame supérieure est retirée de la pile de stockage, entraînant l'annulation de toutes les écritures.

Storage stack frames created with isolated storage enabled

Miniflare déploie des simulateurs pour les services de stockage par-dessus les instances Durable Objects avec un magasin de blob distinct. Lorsqu'il est exécuté localement, workerd utilise SQLite pour le stockage d'instances Durable Objects. Pour mettre en œuvre un stockage isolé, nous déployons une pile de fichiers de base de données .sqlite sur disque en sauvegardant les bases de données lors de la phase de transmission (« push »), puis en restaurant les sauvegardes lors de la phase d'extraction (« pull »). Les blobs stockés dans le magasin distinct sont conservés pendant l'ensemble des opérations sur la pile, puis expurgés à la fin de chaque test. Bien que cette approche fonctionne, elle exige de copier de nombreux fichiers .sqlite . Pour l'avenir, nous aimerions explorer l'utilisation de SAVEPOINTS SQLite, pour produire une solution plus efficace.

Simuler (mock) des requêtes déclaratives

En plus du stockage, la plupart des instances Workers transmettent des requêtes sortantes fetch() . Aux fins des tests, il est souvent utile de simuler les réponses à ces requêtes. Miniflare vous permet déjà de spécifier une instance undici de MockAgent à travers lequel seront acheminées toutes les requêtes. La classe MockAgent fournit une interface déclarative permettant de spécifier les requêtes à simuler (mock) et les réponses correspondantes à renvoyer. Cette API est relativement simple, tout en étant suffisamment flexible pour traiter des scénarios d'utilisation avancés. Nous fournissons une instance de MockAgent sous fetchMock dans le module cloudflare:test.

import { fetchMock } from "cloudflare:test";
import { beforeAll, afterEach, it, expect } from "vitest";

beforeAll(() => {
  // Enable outbound request mocking...
  fetchMock.activate();
  // ...and throw errors if an outbound request isn't mocked
  fetchMock.disableNetConnect();
});
// Ensure we matched every mock we defined
afterEach(() => fetchMock.assertNoPendingInterceptors());

it("mocks requests", async () => {
  // Mock the first request to `https://example.com`
  fetchMock
    .get("https://example.com")
    .intercept({ path: "/" })
    .reply(200, "body");

  const response = await fetch("https://example.com/");
  expect(await response.text()).toBe("body");
});

Pour implémenter cela, nous avons créé un bundle avec une version allégée de undici contenant uniquement le code de MockAgent . Nous avons ensuite créé un Dispatcher undici personnalisé, qui utilise la fonction globale fetch() de l'instance Workers à la place de l'implémentation HTTP intégrée de undici basée sur llhttp et node:net.

Test direct d'instances Durable Objects

Enfin, l'environnement Vitest personnalisé de Miniflare v2 fournissait une prise en charge permettant d'accéder directement aux méthodes et à l'état de l'instance Durable Objects dans les tests. Il vous permettait ainsi de tester les instances Durable Objects comme n'importe quelle autre classe JavaScript – vous pouvez simuler (mock) des méthodes et des propriétés particulières, ou appeler immédiatement des handlers spécifiques tels que alarm(). Pour mettre cela en œuvre dans workerd, nous nous fions à notre notre intégration existante d'instances utilisateur de Durable Objects pour les transformations Vite et le rechargement à chaud de modules. Lorsque vous appelez la fonction runInDurableObject(stub, callback) depuis cloudflare:test, nous stockons callback dans un cache global et transmettons une requête spéciale fetch() à stub, qui est interceptée par le wrapper. Le wrapper exécute callback dans le contexte de la requête de l'instance Durable Objects, et stocke le résultat dans le même cache. runInDurableObject() lit alors les données depuis ce cache, puis renvoie le résultat.

Notez que cela suppose que l'instance Durable Objects s'exécute dans le même isolat que l'appel runInDurableObject(). Bien que cela soit vrai pour les instances Durable Objects partageant la même instance Workers exécutée localement, cela signifie que les instances Durable Objects définies dans les instances Workers auxiliaires ne sont pas directement accessibles.

Essayez !

Nous sommes heureux de publier le package @cloudflare/vitest-pool-workers sur npm et de vous proposer une meilleure expérience de test.

Assurez-vous de lire le guide « Write your first test » (en anglais) et commencez à écrire des tests unitaires et d'intégration dès aujourd'hui ! Si vous avez écrit des tests avec l'une de nos options précédentes, notre guide de migration de unstable_dev ou notre guide de migration de Miniflare v2 devrait expliquer les différences essentielles et vous aider à transférer rapidement vos tests.

Si vous rencontrez des problèmes ou si vous avez des suggestions d'améliorations, veuillez signaler une erreur depuis notre référentiel sur GitHub ou nous contacter via notre Discord pour développeurs.

我们保护整个企业网络,帮助客户高效构建互联网规模的应用程序,加速任何网站或互联网应用程序抵御 DDoS 攻击,防止黑客入侵,并能协助您实现 Zero Trust 的过程

从任何设备访问 1.1.1.1,以开始使用我们的免费应用程序,帮助您更快、更安全地访问互联网。要进一步了解我们帮助构建更美好互联网的使命,请从这里开始。如果您正在寻找新的职业方向,请查看我们的空缺职位
Cloudflare Workers (FR)Developers (FR)Testing (FR)Français

在 X 上关注

Brendan Coll|@_mrbbot
Adam Murray|@admah
Cloudflare|@cloudflare

相关帖子