Testing
The API uses Vitest for testing with a focus on unit and integration tests.
Running Tests
bash
pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm test:run # Run once (CI)Single File
bash
pnpm test src/services/__tests__/BookService.test.tsPattern Matching
bash
pnpm test --grep "BookService"Test Structure
Tests live alongside their source files in __tests__ directories:
src/
├── services/
│ ├── __tests__/
│ │ └── BookService.test.ts
│ └── BookService.tsWriting Tests
Basic Test
typescript
import { describe, it, expect, beforeEach, vi } from "vitest"
describe("BookService", () => {
let service: BookService
let mockRepository: BookRepository
beforeEach(() => {
mockRepository = {
findById: vi.fn(),
create: vi.fn(),
} as unknown as BookRepository
service = new BookService(mockRepository)
})
it("should find a book by id", async () => {
const book = { id: "1", title: "Test Book" }
vi.mocked(mockRepository.findById).mockResolvedValue(book)
const result = await service.findById("1")
expect(result).toEqual(book)
expect(mockRepository.findById).toHaveBeenCalledWith("1")
})
})Testing Controllers
typescript
import { createRequest, createResponse } from "node-mocks-http"
describe("BookController", () => {
it("should return 200 for GET /books", async () => {
const req = createRequest({ method: "GET", url: "/books" })
const res = createResponse()
await controller.getBooks(req, res)
expect(res.statusCode).toBe(200)
})
})Testing with Database
For integration tests, use a test database:
typescript
import { DataSource } from "typeorm"
describe("BookRepository Integration", () => {
let dataSource: DataSource
beforeAll(async () => {
dataSource = await createTestDataSource()
})
afterAll(async () => {
await dataSource.destroy()
})
beforeEach(async () => {
await dataSource.synchronize(true) // Reset database
})
})Mocking
Vitest Mocks
typescript
import { vi } from "vitest"
const mockService = {
findAll: vi.fn().mockResolvedValue([]),
create: vi.fn().mockImplementation((data) => ({ id: "1", ...data })),
}Spying
typescript
const spy = vi.spyOn(service, "create")
await controller.createBook(data)
expect(spy).toHaveBeenCalledWith(data)Test Utilities
Factory Functions
Create test data with factories:
typescript
// test/factories/book.ts
export const createBook = (overrides = {}): Book => ({
id: "test-id",
title: "Test Book",
createdAt: new Date(),
...overrides,
})Assertions
typescript
expect(result).toBeDefined()
expect(result).toHaveLength(3)
expect(result).toContainEqual(expected)
expect(fn).toHaveBeenCalledTimes(1)
expect(fn).toHaveBeenCalledWith(arg1, arg2)Code Coverage
bash
pnpm test --coverageCoverage reports are generated in coverage/.