Mocking a layer in the Effect Typescript library involves creating a test layer that provides a m...
how to mock a layer?
right now I've
I want to mock
how should I correct my approach here:
right now I've
SurrealdbSurrealdb service which relies on DatabaseServiceDatabaseService to establish connection and return an object that interacts w/ the database (select, query, close) :I want to mock
DatabaseServiceDatabaseService and return TestDbLayerTestDbLayer so that Surrealdb.DefaultSurrealdb.Default can use it as a dependency instead of the original onehow should I correct my approach here:
import { expect, describe, layer, beforeEach, vi } from "@effect/vitest"
...
describe("Surrealdb", () => {
const mockSurreal = {
select: vi.fn(),
query: vi.fn(),
close: vi.fn()
}
// Create a test layer with mocked database
const TestDbLayer = Layer.scoped(
DatabaseService,
Effect.acquireRelease(
Effect.sync(() => mockSurreal),
(db) => Effect.promise(() => db.close())
)as unknown as Effect.Effect<DatabaseService, never, Scope.Scope>
)
beforeEach(() => {
vi.resetAllMocks()
mockSurreal.close.mockResolvedValue(undefined)
})
layer(Surrealdb.Default)((it) => {
it.effect("getItem - should retrieve item by id", () =>
Effect.gen(function* () {
mockSurreal.select.mockResolvedValue({ id: "user:123", name: "John" })
const surrealdb = yield* Surrealdb.pipe(Effect.provide(TestDbLayer))
const result = yield* surrealdb.getItem("user", "123")
expect(mockSurreal.select).toHaveBeenCalledWith(new RecordId("user", "123"))
expect(result).toEqual({ id: "user:123", name: "John" })
}))
it.effect("getItem - should handle database error", () =>
Effect.gen(function* () {
const error = new Error("DB failure")
mockSurreal.select.mockRejectedValue(error)
const result = yield* Effect.exit(Surrealdb.pipe(
Effect.flatMap((s) => s.getItem("user", "123"))
))
expect(result).toEqual(Exit.fail(
new SurrealDbError("Couldn't retrieve item user:123", { cause: error })
))
}))import { expect, describe, layer, beforeEach, vi } from "@effect/vitest"
...
describe("Surrealdb", () => {
const mockSurreal = {
select: vi.fn(),
query: vi.fn(),
close: vi.fn()
}
// Create a test layer with mocked database
const TestDbLayer = Layer.scoped(
DatabaseService,
Effect.acquireRelease(
Effect.sync(() => mockSurreal),
(db) => Effect.promise(() => db.close())
)as unknown as Effect.Effect<DatabaseService, never, Scope.Scope>
)
beforeEach(() => {
vi.resetAllMocks()
mockSurreal.close.mockResolvedValue(undefined)
})
layer(Surrealdb.Default)((it) => {
it.effect("getItem - should retrieve item by id", () =>
Effect.gen(function* () {
mockSurreal.select.mockResolvedValue({ id: "user:123", name: "John" })
const surrealdb = yield* Surrealdb.pipe(Effect.provide(TestDbLayer))
const result = yield* surrealdb.getItem("user", "123")
expect(mockSurreal.select).toHaveBeenCalledWith(new RecordId("user", "123"))
expect(result).toEqual({ id: "user:123", name: "John" })
}))
it.effect("getItem - should handle database error", () =>
Effect.gen(function* () {
const error = new Error("DB failure")
mockSurreal.select.mockRejectedValue(error)
const result = yield* Effect.exit(Surrealdb.pipe(
Effect.flatMap((s) => s.getItem("user", "123"))
))
expect(result).toEqual(Exit.fail(
new SurrealDbError("Couldn't retrieve item user:123", { cause: error })
))
}))