# Mock Prisma Schema in Bun Tests

Writing unit tests for your code is usually straightforward when using popular test frameworks like **Jest** or **Vitest**. You can easily mock dependencies and focus your specs on specific units of logic. However, when working with **Bun** — especially if you’re trying to mock Prisma database interactions — things can be a bit different.

In this post, we’ll explore two approaches for mocking Prisma in Bun

## 1.Spying on Methods with `spyOn`

If you want to track method calls (like Prisma Client methods), you can use Bun’s built-in `spyOn` method from `bun:test`. This is ideal when you just want to observe behavior and assert how methods were called.

### Example

```typescript
 import { test, expect, spyOn } from "bun:test";
 import { PrismaClient } from "@prisma/client";
 const prisma = new PrismaClient();

test("should find user by id", async () => {
  const spy = spyOn(prisma.user, "findUnique");
  await prisma.user.findUnique({ where: { id: 1 } });
  expect(spy).toHaveBeenCalledTimes(1);
  expect(spy.mock.calls[0][0]).toEqual({ where: { id: 1 } });
});
```

## 2.Mock the Entire Module

Consider this example: we have a function that fetches a user from the database based on an ID.

```typescript
import { getDbClient } from '~/lib/getDbClient';

export async function findUser(id: number) {
  const db = getDbClient();
  const user = await db.user.findUnique({ where: { entity_id: id } });

  if (!user) return { status: 'redirect', redirectUrl: href('/login')};

  return { status: 'valid', user };
}
```

Here, `getDbClient()` returns the Prisma instance, and we use its `findUnique()` method to locate a user.

### The Challenge

If we try to test this directly, it will attempt to call the actual database. That’s undesirable for a unit test, so we need a way to **mock the Prisma client**.

### The Solution: `mockModule`

We can accomplish this using Bun’s `mock.module()` method. Here’s how:

#### Creating a Mock User

First, we create a helper method:

```typescript
function createMockUser(overrides: Partial<UserEntity> = {}): UserEntity {
  const defaultUser = {
    email: 'john@example.com',
    created_at: new Date(),
    updated_at: new Date(),
    is_active: 1,
    firstname: 'John',
    lastname: 'Doe',
    dob: null,
    gender: null,
    password_hash: null,
  };

  return {
    ...defaultUser,
    ...overrides,
  };
}
```

#### Writing the Spec

Then, we use `mockModule()` in our test:

Then we will write the spec for the function by mocking the dbClient like below

```typescript
import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
import { mockModule } from '~/lib/mockModule';

describe('findUser', () => {
  beforeEach(() => {
    mock.module('~/lib/getDbClient', () => ({}));
  });

  afterEach(() => {
    mock.restore();
  });

  it('should redirect if user not found', async () => {
    using mocked = await mockModule('~/lib/getDbClient', () => ({
      getDbClient: () => ({
        user_entity: {
          findUnique: () => null,
        },
      }),
    }));

    const result = await findUser(1);
    assertRedirect(result, '/login?msg=link_expired&link_error=2');
  });

  it('should return valid user', async () => {
    const mockUser = createMockUser();

    using mocked = await mockModule('~/lib/getDbClient', () => ({
      getDbClient: () => ({
        user_entity: {
          findUnique: () => mockUser,
        },
      }),
    }));

    const result = await findUser(1);
    expect(result.status).toBe('valid');
    if (result.status === 'valid') {
      expect(result.user).toEqual(mockUser);
    }
  });
});
```

### The `mockModule` Utility

Here’s the helper used to swap in and restore mock implementations:

```typescript
import { mock } from 'bun:test';

/**
 * Mocks a module by merging its actual exports with custom implementations.
 */
export const mockModule = async (
  modulePath: string,
  renderMocks: () => Record<string, any>
) => {
  const original = { ...(await import(modulePath)) };
  const mocks = renderMocks();
  const result = {
    ...original,
    ...mocks,
  };
  mock.module(modulePath, () => result);
  return {
    [Symbol.dispose]: () => {
      mock.module(modulePath, () => original);
    },
  };
};
```

With this approach, you can effectively **mock Prisma instances** in Bun, making your specs focused and independent of actual database connections — all without relying on Jest or Vitest.

If you’re migrating to Bun or starting fresh, this method gives you a clean, reliable way to test database-related logic in isolation.
