mcpField
E
effect-testing-mocking

effect-testing-mocking

github.com/mepukaテスト・品質537 回インストール44 週間前に更新
リポジトリ

effect-testing-mocking について

Effect 開発者向けに、モックサービスと Layer を使った決定的なテスト方法を案内するスキルです。テスト API の実装前に、ローカルの Effect ソースを確認する手順も示します。

主な機能

  1. 01Layer によるサービスのモック
  2. 02テスト実装の明示的な提供
  3. 03決定的なテストクロックの利用
  4. 04ローカル Effect ソースの優先確認

活用シーン

  1. 01外部 I/O なしでプログラムをテスト
  2. 02サービス依存をモックに置き換え
  3. 03時間依存の動作を決定的に検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mepuka/effect-ontology --skill effect-testing-mocking

インストール後、Claude Code で/effect-testing-mockingを入力して読み込まれたか確認します。

詳細

テストとモック

使用する場面

  • 外部 I/O を使わずに、決定的なテストを実行したい場合
  • レイヤーを通じてモックサービスを注入したい場合

モックレイヤー

const RepoTest = Layer.succeed(Repo, Repo.of({ find: () => Effect.succeed(mock) }))

テスト実装の提供

const result = yield* Effect.provide(program, RepoTest)

テストクロック

// Provide a deterministic Clock or use platform TestClock layer if available

ガイダンス

  • テストの対象を絞って高速に保ち、サービスをモックしてネットワークアクセスを避けます
  • プログラムの要件に合わせて、レイヤーを明示的に提供します
  • テストを実際のインターフェースに近づけ、テストのためにアプリケーションコードの形を変えないようにします
  • 手早く配線するには .Default レイヤーを使い、テストごとにカスタムのモックレイヤーを追加します
  • すばやく実行でき、すぐに失敗する小規模なスモークテストを優先します

注意点

  • テストに実際の I/O が入り込むと、不安定になります
  • 内部実装を過剰にモックすると、テストが壊れやすくなります。サービス境界でモックしてください

関連リンク

  • DI パターンについては「レイヤーとサービス」を参照してください
  • 決定的な時刻と観測可能な出力については「時刻とログ」を参照してください

ローカルソースの参照

重要:実装する前に Effect のローカルソースを検索してください

Effect のソースコード全体は docs/effect-source/ にあります。Effect コードを書く前に、必ず実際の実装を検索してください。

主なソースファイル
  • Layer:docs/effect-source/effect/src/Layer.ts
  • TestClock:docs/effect-source/effect/src/TestClock.ts
  • TestContext:docs/effect-source/effect/src/TestContext.ts
検索例
# Find Layer.succeed patterns for mocks
grep -F "Layer.succeed" docs/effect-source/effect/src/Layer.ts

# Study TestClock operations
grep -F "TestClock" docs/effect-source/effect/src/TestClock.ts

# Find test helpers
grep -F "TestContext" docs/effect-source/effect/src/TestContext.ts

# Look at Layer test examples
grep -F "Layer.succeed" docs/effect-source/effect/test/Layer.test.ts
ワークフロー
  1. 必要なテスト API を特定します(例:Layer.succeed、TestClock)
  2. docs/effect-source/effect/src/Layer.ts で実装を検索します
  3. 型とテストのパターンを調べます
  4. 使用例について、テストファイルを確認します
  5. 実際の実装に基づいてコードを書きます

実際のソースコード > ドキュメント > 推測

実例:包括的なテストレイヤーを構築する

export const TestLayer = (input?: TestLiveInput) =>
  Effect.gen(function* () {
    const tempDir = tempy.temporaryDirectory({ prefix: 'test' })
    const cwd = (yield* setupFixtureFolder({ fixture: input?.fixture, tempDir })) ?? tempDir

    const NodeOsTest = Layer.succeed(NodeOs, new NodeOs({ homedir: cwd, arch: 'arm64', platform: 'darwin' }))
    const NodeProcessTest = Layer.succeed(NodeProcess, new NodeProcess({ cwd, platform: 'darwin', arch: 'arm64' }))

    const ToolkitsRepoTest = Layer.succeed(ComposioToolkitsRepository, new ComposioToolkitsRepository({
      getToolkits: () => Effect.succeed([]),
      getToolsAsEnums: () => Effect.succeed([])
    }))

    const layers = Layer.mergeAll(
      Console.setConsole(yield* MockConsole.effect),
      CliConfig.layer(ComposioCliConfig),
      NodeProcessTest,
      Layer.provideMerge(ComposioUserContextLive, Layer.merge(BunFileSystem.layer, NodeOsTest)),
      ToolkitsRepoTest,
      EnvLangDetector.Default,
      JsPackageManagerDetector.Default,
      BunFileSystem.layer,
      BunContext.layer,
      MockTerminal.layer,
      BunPath.layer
    )

    return layers
  }).pipe(
    Logger.withMinimumLogLevel(LogLevel.Debug),
    Effect.scoped,
    Layer.unwrapEffect,
    Layer.provide(Layer.setConfigProvider(input?.baseConfigProvider ?? ConfigProvider.fromMap(new Map([]))))
  )

参考資料

コメント