Use this file to discover all available pages before exploring further.
Effect provides first-class testing support through @effect/vitest, which integrates Effect’s runtime with Vitest. Write tests using familiar syntax while leveraging Effect’s powerful features like dependency injection, time control, and structured concurrency.
Define test-specific layers that provide mock implementations:
import { assert, describe, it, layer } from "@effect/vitest"import { Array, Effect, Layer, Ref, ServiceMap } from "effect"export interface Todo { readonly id: number readonly title: string}// Create a test ref service that can be used to store test dataexport class TodoRepoTestRef extends ServiceMap.Service<TodoRepoTestRef, Ref.Ref<Array<Todo>>>()("app/TodoRepoTestRef"){ static readonly layer = Layer.effect(TodoRepoTestRef, Ref.make(Array.empty()))}class TodoRepo extends ServiceMap.Service<TodoRepo, { create(title: string): Effect.Effect<Todo> readonly list: Effect.Effect<ReadonlyArray<Todo>>}>()("app/TodoRepo") { static readonly layerTest = Layer.effect( TodoRepo, Effect.gen(function*() { const store = yield* TodoRepoTestRef const create = Effect.fn("TodoRepo.create")(function*(title: string) { const todos = yield* Ref.get(store) const todo = { id: todos.length + 1, title } yield* Ref.set(store, [...todos, todo]) return todo }) const list = Ref.get(store) return TodoRepo.of({ create, list }) }) ).pipe( // Provide the test ref layer as a dependency Layer.provideMerge(TodoRepoTestRef.layer) )}
Use the layer() helper to create one shared layer for all tests in a block:
// layer(...) creates one shared layer for the block and tears it down in// afterAll, so all tests inside can access the same service context.layer(TodoRepo.layerTest)("TodoRepo", (it) => { it.effect("tests repository behavior", () => Effect.gen(function*() { const repo = yield* TodoRepo const before = (yield* repo.list).length assert.strictEqual(before, 0) yield* repo.create("Write docs") const after = (yield* repo.list).length assert.strictEqual(after, 1) })) it.effect("layer is shared", () => Effect.gen(function*() { const repo = yield* TodoRepo const before = (yield* repo.list).length // State from previous test persists because layer is shared assert.strictEqual(before, 1) yield* repo.create("Write docs again") const after = (yield* repo.list).length assert.strictEqual(after, 2) }))})
// Each test gets fresh layers by using Effect.providedescribe("isolated tests", () => { it.effect("test 1", () => Effect.gen(function*() { const service = yield* MyService // Fresh service instance }).pipe(Effect.provide(MyService.layerTest))) it.effect("test 2", () => Effect.gen(function*() { const service = yield* MyService // Another fresh service instance }).pipe(Effect.provide(MyService.layerTest)))})
// Use layer() for shared state across testslayer(MyService.layerTest)("shared tests", (it) => { it.effect("test 1", () => Effect.gen(function*() { const service = yield* MyService // Shared service instance })) it.effect("test 2", () => Effect.gen(function*() { const service = yield* MyService // Same service instance as test 1 }))})