---
title: Testing in Better Auth
description: Testing Guide for Better Auth
---

## Overview

We use Vitest as our testing framework of choice. Currently, we focus on unit tests, with plans to expand to integration testing in the future.
This guide will help you understand our testing philosophy and how to write effective tests.

<Callout type="warn">
  We expect you to have knowledge of Vitest before you start writing tests. If
  you're new to Vitest, we recommend you read the [Vitest
  documentation](https://vitest.dev/guide/) first.
</Callout>

## Testing Philosophy

Our approach to testing emphasizes:

- Simplicity over complexity
- Real implementations over mocks
- Co-location of tests with source code
- Minimal test setup
- Clear and readable test cases

## Getting Started

### Setup

```bash
# Install dependencies including Vitest
pnpm install

# Run tests
pnpm run test
```

## Test Structure

### File Organization

We follow a co-location strategy for tests. Place your test files next to the source files they test:

<Files>
  <Folder name="auth" defaultOpen>
    <File name="auth.ts" />
    <File name="auth.test.ts" />
  </Folder>
  <Folder name="plugins" defaultOpen>
    <File name="oauth.ts" />
    <File name="oauth.test.ts" />
  </Folder>
</Files>

### Test File Naming

- Use `.test.ts` extension for test files
- Name test files after the module they test
- For TypeScript, use `.test.ts` or `.test.tsx` for React components

## Writing Tests

### Basic Test Structure

<Callout type="info">
  This is just example code, and isn't meant to be used as-is. It's meant to
  demonstrate the structure of a test file.
</Callout>

```ts title="auth.test.ts"
//...
import { describe, it, expect } from "vitest";
import { getTestInstance } from "./test-utils/test-instance";

describe("Authentication Module", () => {
  it("should successfully authenticate a user", async () => {
    const { client } = getTestInstance();
    const result = await client.signIn.email({
      email: "hello@gmail.com",
      password: "123456",
    });

    expect(result.success).toBe(true);
    expect(result.user).toBeDefined();
  });
});
```

### Using `getTestInstance`

The test instance provides multiple handy properties that you can use to test your feature.

```ts
import { getTestInstance } from "../test-utils";

const {
  client,
  auth,
  cookieSetter,
  customFetchImpl,
  db,
  sessionSetter,
  signInWithTestUser,
  signInWithUser,
  testUser,
} = getTestInstance();
```

Only create custom instances when needed

```typescript
import { getTestInstance } from "../test-utils";

const { auth } = getTestInstance({
  customConfig: {
    // your custom configuration
  },
});
```

## Best Practices

### Do's

- Write descriptive test names that explain the expected behavior
- Test both success and failure cases
- Keep tests focused and atomic
- Use setup and teardown when needed
- Test edge cases and boundary conditions

<Callout type="info">
  This is just example code, and isn't meant to be used as-is. It's meant to
  demonstrate the best Practices of testing.
</Callout>

```typescript
describe("User Authentication", () => {
  it("should reject invalid credentials", async () => {
    const { client } = getTestInstance();
    const result = await client.signIn.email({
      email: "invalid@example.com",
      password: "wrong",
    });

    expect(result.success).toBe(false);
    expect(result.error).toBeDefined();
  });

  it("should handle empty inputs appropriately", async () => {
    const { client } = getTestInstance();
    const result = await client.signIn.email({
      email: "",
      password: "",
    });

    expect(result.success).toBe(false);
    expect(result.error).toMatch(/required/);
  });
});
```

### Don'ts

- Don't create unnecessary mocks
- Don't test implementation details
- Don't create separate test folders
- Don't write brittle tests
- Don't test external libraries

## Future Plans

- Implement integration testing
- Add end-to-end testing
- Expand API testing coverage
- Add performance testing
- Implement snapshot testing where appropriate

## Contributing

When submitting a PR:

- Ensure all tests pass
- Add tests for new features
- Update tests for modified features
- Follow existing test patterns
- Include meaningful assertions

Need help? Feel free to reach out in our <Link href="https://discord.gg/GYC3W7tZzb">Discord server</Link>!
