better-effect
better-effect-mq

Testing

Test the real JobStore and Worker with deterministic controls.

The better-effect-mq/testing entrypoint is runner-neutral. TestJobStore wraps the real MemoryJobStore contract and keeps a ClockTest, an IdGeneratorTest, a store Layer and a recorded observer together. It does not mutate private state or implement a second Worker.

The following continuation uses the canonical SendEmail descriptor from Defining Jobs and observes it with TestJobStore; it does not declare a second test-only Job.

import { Effect } from 'better-effect'
import { ClockTest, IdGeneratorTest } from 'better-effect/standard-services'
import { TestRuntime } from 'better-effect/testing'
import { Result } from 'better-result'
import { TestJobStore } from 'better-effect-mq/testing'

const clock = new ClockTest(Date.UTC(2026, 0, 1))
const ids = IdGeneratorTest.from((index) => `job-${index + 1}`)
const testStore = TestJobStore.make({ clock, ids })
const runtime = await TestRuntime.make(testStore.layer, {
  clock,
  idGenerator: ids
})

try {
  const id = await runtime.run(() =>
    Effect.gen(async function* () {
      const value = yield* SendEmail.enqueue({
        messageId: 'message-test-1',
        recipient: 'ada@example.test'
      })
      return Result.ok(value)
    })
  )
  if (Result.isError(id)) throw id.error
  console.log(await testStore.enqueuedPayloads(SendEmail))
} finally {
  await runtime.dispose()
}

The harness assertions are oldest-first and readonly: enqueued, enqueuedPayloads, job, attempts and counts. claim, settle and release call the public contract with explicit lease tokens. Named stores use TestJobStore.makeFor(namedToken, options).

The test Job reuses the canonical Zod 4 schema-backed class from better-effect-schema through Codec.standardSchema, matching the recommended production boundary. Keep the trusted JSON escape hatch for intentionally trusted JSON fixtures that do not need runtime validation.

For Worker scenarios, start the real Worker through the test Runtime's public Layer composition and use ClockTest, a deterministic random source and a zero-delay persisted backoff. Assert the completed/failed record and attempt ledger after awaitIdle; advance the test clock for delayed Jobs instead of replacing Date or using arbitrary sleeps. Also cover Result.err, defects, cleanup failures, cooperative cancellation, lease expiry and named-store isolation.

The lower-level jobStoreContract exercises adapter conformance. Use it for store implementations; use TestJobStore for focused application tests.