MockServer Testing
The MockServer is Balda.js's powerful testing utility that allows you to test HTTP endpoints without starting a real server. This enables fast, isolated testing of your controllers and middleware.
Overview
MockServer simulates HTTP requests by:
- Executing the complete middleware chain
- Running route handlers with mocked request/response objects
- Providing realistic testing environment without network overhead
- Supporting all HTTP methods and content types
Basic Usage
import { describe, it, expect } from "vitest";
import server from "../src/server"; // Main Server instance
// MockServer instance that imitates HTTP requests defined in your server (without actually executing network calls)
const mockServer = server.getMockServer();
describe("API Tests", () => {
it("GET /users returns all users", async () => {
const res = await mockServer.get("/users");
expect(res.statusCode()).toBe(200);
expect(Array.isArray(res.body())).toBe(true);
});
});
HTTP Methods
MockServer provides methods for all HTTP verbs:
GET Requests
// Simple GET request
const res = await mockServer.get("/users");
// GET with query parameters
const res = await mockServer.get("/users", {
query: { page: "1", limit: "10" }
});
// GET with headers
const res = await mockServer.get("/users", {
headers: { "Authorization": "Bearer token123" }
});
POST Requests
// POST with JSON body
const res = await mockServer.post("/users", {
body: { name: "John", email: "john@example.com" }
});
// POST with form data
const res = await mockServer.post("/users", {
urlencoded: { name: "John", email: "john@example.com" }
});
// POST with file upload
const formData = new FormData();
formData.append("file", new Blob(["content"]), "test.txt");
const res = await mockServer.post("/upload", { formData });
Other HTTP Methods
// PUT request
const res = await mockServer.put("/users/1", {
body: { name: "Updated Name" }
});
// PATCH request
const res = await mockServer.patch("/users/1", {
body: { name: "Patched Name" }
});
// DELETE request
const res = await mockServer.delete("/users/1");
Request Options
MockServer supports comprehensive request configuration:
interface MockServerOptions {
headers?: Record<string, string>;
query?: Record<string, string>;
cookies?: Record<string, string>;
ip?: string;
body?: any;
formData?: FormData;
urlencoded?: Record<string, string>;
}
Headers
const res = await mockServer.get("/protected", {
headers: {
"Authorization": "Bearer token123",
"Content-Type": "application/json"
}
});
Query Parameters
const res = await mockServer.get("/search", {
query: {
q: "search term",
page: "1",
limit: "20"
}
});
Cookies
const res = await mockServer.get("/profile", {
cookies: {
sessionId: "abc123",
userId: "456"
}
});
IP Address
const res = await mockServer.get("/location", {
ip: "192.168.1.1"
});
Response Assertions
MockResponse provides powerful assertion methods:
Status Code Assertions
const res = await mockServer.get("/users");
expect(res.statusCode()).toBe(200);
expect(res.assertStatus(200)); // Alternative syntax
Body Assertions
// Exact body match
expect(res.assertBodyDeepEqual({ id: 1, name: "John" }));
// Partial body match
expect(res.assertBodySubset({ name: "John" }));
// Get body content
const body = res.body();
expect(body.name).toBe("John");
Complete Example
describe("User API", () => {
it("creates a new user", async () => {
const newUser = {
name: "Jane Doe",
email: "jane@example.com",
age: 25
};
const res = await mockServer.post("/users", { body: newUser });
expect(res.assertStatus(201));
expect(res.assertBodyDeepEqual(newUser));
});
it("returns 404 for non-existent user", async () => {
const res = await mockServer.get("/users/999");
expect(res.assertStatus(404));
expect(res.assertBodyDeepEqual({ error: "User not found" }));
});
});
File Upload Testing
MockServer supports file upload testing with FormData:
describe("File Upload", () => {
it("uploads a file successfully", async () => {
const formData = new FormData();
const fileContent = new Uint8Array([1, 2, 3, 4, 5]);
formData.append("file", new Blob([fileContent]), "test.txt");
const res = await mockServer.post("/upload", { formData });
expect(res.assertStatus(200));
expect(res.body()).toEqual({
originalName: "test.txt",
filename: "file",
size: 5,
mimetype: "application/octet-stream"
});
});
});
Error Handling
MockServer properly handles and reports errors:
describe("Error Handling", () => {
it("handles server errors gracefully", async () => {
const res = await mockServer.get("/users", {
query: { shouldFail: "true" }
});
expect(res.assertStatus(500));
expect(res.body()).toHaveProperty("error");
});
});
Best Practices
1. Test Isolation
describe("User Management", () => {
// Each test should be independent
it("creates user", async () => {
// Test implementation
});
it("updates user", async () => {
// Test implementation - doesn't depend on previous test
});
});
2. Descriptive Test Names
// Good
it("POST /users returns 409 when user already exists", async () => {
// Test implementation
});
// Avoid
it("test user creation", async () => {
// Test implementation
});
3. Use TypeScript
interface UserResponse {
id: number;
name: string;
email: string;
}
const res = await mockServer.get<UserResponse[]>("/users");
const users = res.body() as UserResponse[];
4. Test Edge Cases
describe("User Validation", () => {
it("rejects invalid email format", async () => {
const res = await mockServer.post("/users", {
body: { name: "John", email: "invalid-email" }
});
expect(res.assertStatus(400));
});
it("requires all mandatory fields", async () => {
const res = await mockServer.post("/users", {
body: { name: "John" } // Missing email
});
expect(res.assertStatus(400));
});
});
Advanced Features
Custom Request Configuration
const res = await mockServer.request("GET", "/api/data", {
headers: {
"X-Custom-Header": "value",
"Authorization": "Bearer token"
},
query: { filter: "active" },
cookies: { sessionId: "abc123" },
ip: "192.168.1.100"
});
Testing Middleware
MockServer executes the complete middleware chain, allowing you to test:
- Authentication middleware
- Rate limiting
- CORS handling
- Request logging
- Custom business logic middleware
This comprehensive testing approach ensures your entire request pipeline works correctly in isolation.