This document provides guidelines and examples for testing API endpoints in our application using Vitest.
We use the following tools for API testing:
- Vitest: Fast testing framework powered by Vite
- node-mocks-http: For mocking HTTP requests and responses
- vi.mock(): For mocking dependencies like Prisma, Next Auth, etc.
API tests should be placed in a __tests__
directory adjacent to the API file being tested, with a .test.ts
extension.
Example:
src/
pages/
api/
is-dotabod-live.ts
__tests__/
is-dotabod-live.test.ts
Here's a basic template for testing an API endpoint:
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { createMocks } from 'node-mocks-http'
import handler from '../your-api-file'
// Mock dependencies
vi.mock('@/lib/db', () => ({
default: {
// Mock your database models and methods
},
}))
// Import mocked modules
import prisma from '@/lib/db'
describe('Your API Name', () => {
beforeEach(() => {
vi.resetAllMocks()
})
afterEach(() => {
vi.clearAllMocks()
})
it('handles successful requests', async () => {
// Create mock request and response
const { req, res } = createMocks({
method: 'GET',
query: { /* query params */ },
body: { /* request body */ },
})
// Mock database responses
vi.mocked(prisma.model.method).mockResolvedValueOnce(/* mock data */)
// Call the handler
await handler(req, res)
// Assert response
expect(res.statusCode).toBe(200)
expect(res._getJSONData()).toEqual(/* expected response */)
})
it('handles error cases', async () => {
// Similar structure for error cases
})
})
Test different HTTP methods by setting the appropriate method in the mock request:
const { req, res } = createMocks({
method: 'POST', // or 'GET', 'PUT', 'DELETE', etc.
})
Mock Prisma database calls using vi.mock()
:
vi.mock('@/lib/db', () => ({
default: {
user: {
findFirst: vi.fn(),
},
},
}))
// Then in your test
vi.mocked(prisma.user.findFirst).mockResolvedValueOnce({
id: 'user-123',
name: 'Test User',
})
For endpoints that require authentication, mock the authentication process:
vi.mock('next-auth', () => ({
getServerSession: vi.fn(),
}))
// Mock authenticated session
vi.mocked(getServerSession).mockResolvedValueOnce({
user: { id: 'user-123' },
})
// Mock unauthenticated session
vi.mocked(getServerSession).mockResolvedValueOnce(null)
Test how your API handles errors by mocking rejected promises:
// Mock database error
const mockError = new Error('Database error')
vi.mocked(prisma.user.findFirst).mockRejectedValueOnce(mockError)
// Assert error response
expect(res.statusCode).toBe(500)
expect(res._getJSONData()).toEqual({ error: 'Error message' })
For endpoints that call external APIs, mock the fetch function:
global.fetch = vi.fn()
// Mock successful response
global.fetch = vi.fn().mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({ data: 'response data' }),
})
// Mock failed response
global.fetch = vi.fn().mockRejectedValueOnce(new Error('Fetch error'))
Run API tests using the following commands:
# Run all tests
bun run test
# Run specific API tests
bun run test --run api-file-name
- Test all paths: Test successful requests, error cases, and edge cases.
- Mock all external dependencies: Database, authentication, external APIs, etc.
- Verify correct parameters: Check that your API calls external services with the correct parameters.
- Test response structure: Verify that the API returns the expected response structure.
- Test HTTP status codes: Verify that the API returns the correct HTTP status codes.
- Reset mocks between tests: Use
beforeEach
andafterEach
to reset mocks between tests. - Isolate tests: Each test should be independent of others.
See the following test files for examples:
src/pages/api/__tests__/is-dotabod-live.test.ts
: Simple GET endpoint with database querysrc/pages/api/__tests__/languages.test.ts
: API that calls an external servicesrc/pages/api/user/__tests__/gift-subscriptions.test.ts
: Authenticated API with complex response
This test suite verifies the functionality of the gift alert API endpoint, which is used to retrieve and mark as read gift subscription notifications. The tests use a mock handler approach to simulate the API behavior without relying on actual database calls.
Tests include:
- Authentication validation
- Handling missing notifications
- Retrieving notification details
- Marking notifications as read
- Error handling
This test suite verifies the functionality of the test gift notification API endpoint, which is used by administrators to create test gift notifications in the development environment. The tests use a mock handler approach to simulate the API behavior.
Tests include:
- Environment validation (development only)
- Authentication and authorization validation
- Gift type validation
- Gift quantity validation
- Creating monthly gift notifications
- Creating lifetime gift notifications
This test suite verifies the functionality of the by-username API endpoint, which retrieves subscription information for a given username. The tests cover various scenarios including missing usernames, user not found, and different subscription tiers.
Tests include:
- Handling missing username parameter
- Handling user not found
- Returning FREE tier for users without subscriptions
- Returning PRO tier for active, lifetime, and gift subscriptions
- Handling grace periods
- Error handling