Преглед изворни кода

test(server): use Layer.mock for partial Account service stub (#26472)

Kit Langton пре 4 месеци
родитељ
комит
7f3e51453b

+ 16 - 0
packages/opencode/test/AGENTS.md

@@ -142,3 +142,19 @@ Use `provideTmpdirInstance(...)` or `tmpdirScoped()` plus `provideInstance(...)`
 - Yield services directly with `yield* MyService.Service` or `yield* MyTool`.
 - Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers when `testEffect(...)` already provides the runtime.
 - When a test needs instance-local state, prefer `it.instance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
+
+### Partial Service Stubs
+
+When a test only needs to override one or two methods of a service, prefer `Layer.mock` over a hand-rolled `Layer.succeed(Service, Service.of({ ... }))`. `Layer.mock` lets you supply just the methods that matter — anything else throws an `UnimplementedError` defect if the test accidentally calls it, which is exactly the signal you want.
+
+```typescript
+import { Effect, Layer } from "effect"
+import { Account } from "@/account/account"
+
+const failingAccountLayer = Layer.mock(Account.Service, {
+  orgsByAccount: () =>
+    Effect.fail(new Account.AccountServiceError({ message: "simulated upstream failure" })),
+})
+```
+
+This is much shorter than stubbing every method with `Effect.void` / `Effect.succeed(...)` placeholders, and it keeps the test focused on the behaviour under test.

+ 5 - 17
packages/opencode/test/server/httpapi-account-error-mapping.test.ts

@@ -1,5 +1,5 @@
 import { afterEach, describe, expect, mock, test } from "bun:test"
-import { Effect, Layer, Option } from "effect"
+import { Effect, Layer } from "effect"
 
 // Account.orgsByAccount() can fail with AccountServiceError when the
 // upstream Anthropic Console API is unreachable. The HTTP API used to
@@ -17,22 +17,10 @@ import { Effect, Layer, Option } from "effect"
 
 const ORIG = await import("../../src/account/account")
 
-const failingAccountLayer = Layer.succeed(
-  ORIG.Service,
-  ORIG.Service.of({
-    active: () => Effect.succeed(Option.none()),
-    activeOrg: () => Effect.succeed(Option.none()),
-    list: () => Effect.succeed([]),
-    orgsByAccount: () => Effect.fail(new ORIG.AccountServiceError({ message: "simulated upstream failure" })),
-    remove: () => Effect.void,
-    use: () => Effect.void,
-    orgs: () => Effect.succeed([]),
-    config: () => Effect.succeed(Option.none()),
-    token: () => Effect.succeed(Option.none()),
-    login: () => Effect.fail(new ORIG.AccountServiceError({ message: "unused" })),
-    poll: () => Effect.fail(new ORIG.AccountServiceError({ message: "unused" })),
-  }),
-)
+const failingAccountLayer = Layer.mock(ORIG.Service, {
+  orgsByAccount: () =>
+    Effect.fail(new ORIG.AccountServiceError({ message: "simulated upstream failure" })),
+})
 
 const mocked = {
   ...ORIG,