359 lines
9.1 KiB
Go
359 lines
9.1 KiB
Go
/*
|
||
server_test.go - Web服务器测试文件
|
||
测试HTTP服务器和API的各种功能
|
||
*/
|
||
|
||
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"testing"
|
||
|
||
"webserver/models"
|
||
"webserver/server"
|
||
)
|
||
|
||
// TestHealthHandler 测试健康检查处理器
|
||
func TestHealthHandler(t *testing.T) {
|
||
req, err := http.NewRequest("GET", "/health", nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.HealthHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusOK {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusOK)
|
||
}
|
||
|
||
// 检查响应内容类型
|
||
expected := "application/json"
|
||
if ct := rr.Header().Get("Content-Type"); ct != expected {
|
||
t.Errorf("处理器返回错误内容类型: got %v want %v", ct, expected)
|
||
}
|
||
|
||
// 检查响应体
|
||
var response server.HealthResponse
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if response.Status != "healthy" {
|
||
t.Errorf("期望状态为 'healthy', 实际为 '%s'", response.Status)
|
||
}
|
||
}
|
||
|
||
// TestGetUsersHandler 测试获取用户列表处理器
|
||
func TestGetUsersHandler(t *testing.T) {
|
||
req, err := http.NewRequest("GET", "/api/users", nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.GetUsersHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusOK {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusOK)
|
||
}
|
||
|
||
// 检查响应内容类型
|
||
expected := "application/json"
|
||
if ct := rr.Header().Get("Content-Type"); ct != expected {
|
||
t.Errorf("处理器返回错误内容类型: got %v want %v", ct, expected)
|
||
}
|
||
|
||
// 检查响应体
|
||
var response server.Response
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if response.Status != "success" {
|
||
t.Errorf("期望状态为 'success', 实际为 '%s'", response.Status)
|
||
}
|
||
}
|
||
|
||
// TestCreateUserHandler 测试创建用户处理器
|
||
func TestCreateUserHandler(t *testing.T) {
|
||
user := models.User{
|
||
Name: "测试用户",
|
||
Email: "test@example.com",
|
||
Age: 25,
|
||
}
|
||
|
||
jsonData, err := json.Marshal(user)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
req, err := http.NewRequest("POST", "/api/users", bytes.NewBuffer(jsonData))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.CreateUserHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusCreated {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusCreated)
|
||
}
|
||
|
||
// 检查响应体
|
||
var response server.Response
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if response.Status != "success" {
|
||
t.Errorf("期望状态为 'success', 实际为 '%s'", response.Status)
|
||
}
|
||
}
|
||
|
||
// TestCreateUserHandlerInvalidData 测试创建用户处理器(无效数据)
|
||
func TestCreateUserHandlerInvalidData(t *testing.T) {
|
||
// 测试空用户名
|
||
user := models.User{
|
||
Name: "",
|
||
Email: "test@example.com",
|
||
Age: 25,
|
||
}
|
||
|
||
jsonData, err := json.Marshal(user)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
req, err := http.NewRequest("POST", "/api/users", bytes.NewBuffer(jsonData))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.CreateUserHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusBadRequest {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusBadRequest)
|
||
}
|
||
|
||
// 检查响应体
|
||
var response server.Response
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if response.Status != "error" {
|
||
t.Errorf("期望状态为 'error', 实际为 '%s'", response.Status)
|
||
}
|
||
}
|
||
|
||
// TestCreateUserHandlerInvalidJSON 测试创建用户处理器(无效JSON)
|
||
func TestCreateUserHandlerInvalidJSON(t *testing.T) {
|
||
invalidJSON := []byte(`{"name": "测试用户", "email": "test@example.com", "age":}`)
|
||
|
||
req, err := http.NewRequest("POST", "/api/users", bytes.NewBuffer(invalidJSON))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.CreateUserHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusBadRequest {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusBadRequest)
|
||
}
|
||
}
|
||
|
||
// TestStatsHandler 测试统计信息处理器
|
||
func TestStatsHandler(t *testing.T) {
|
||
req, err := http.NewRequest("GET", "/api/stats", nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.StatsHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusOK {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusOK)
|
||
}
|
||
|
||
// 检查响应体
|
||
var response server.StatsResponse
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if response.Status != "success" {
|
||
t.Errorf("期望状态为 'success', 实际为 '%s'", response.Status)
|
||
}
|
||
|
||
if response.NumCPU <= 0 {
|
||
t.Error("CPU数量应该大于0")
|
||
}
|
||
|
||
if response.NumGoroutine <= 0 {
|
||
t.Error("Goroutine数量应该大于0")
|
||
}
|
||
}
|
||
|
||
// TestAPIDocHandler 测试API文档处理器
|
||
func TestAPIDocHandler(t *testing.T) {
|
||
req, err := http.NewRequest("GET", "/api", nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.APIDocHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查状态码
|
||
if status := rr.Code; status != http.StatusOK {
|
||
t.Errorf("处理器返回错误状态码: got %v want %v", status, http.StatusOK)
|
||
}
|
||
|
||
// 检查响应内容类型
|
||
expected := "application/json"
|
||
if ct := rr.Header().Get("Content-Type"); ct != expected {
|
||
t.Errorf("处理器返回错误内容类型: got %v want %v", ct, expected)
|
||
}
|
||
|
||
// 检查响应体包含API文档信息
|
||
var doc map[string]interface{}
|
||
if err := json.Unmarshal(rr.Body.Bytes(), &doc); err != nil {
|
||
t.Errorf("无法解析响应JSON: %v", err)
|
||
}
|
||
|
||
if _, exists := doc["title"]; !exists {
|
||
t.Error("API文档应该包含title字段")
|
||
}
|
||
|
||
if _, exists := doc["endpoints"]; !exists {
|
||
t.Error("API文档应该包含endpoints字段")
|
||
}
|
||
}
|
||
|
||
// TestServer 测试完整的服务器
|
||
func TestServer(t *testing.T) {
|
||
// 创建服务器
|
||
srv := server.NewServer(":0") // 使用随机端口
|
||
srv.SetupRoutes()
|
||
|
||
// 创建测试服务器
|
||
testServer := httptest.NewServer(srv.GetRouter())
|
||
defer testServer.Close()
|
||
|
||
// 测试健康检查
|
||
resp, err := http.Get(testServer.URL + "/health")
|
||
if err != nil {
|
||
t.Fatalf("健康检查请求失败: %v", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
if resp.StatusCode != http.StatusOK {
|
||
t.Errorf("健康检查返回错误状态码: got %v want %v", resp.StatusCode, http.StatusOK)
|
||
}
|
||
|
||
// 测试获取用户列表
|
||
resp, err = http.Get(testServer.URL + "/api/users")
|
||
if err != nil {
|
||
t.Fatalf("获取用户列表请求失败: %v", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
if resp.StatusCode != http.StatusOK {
|
||
t.Errorf("获取用户列表返回错误状态码: got %v want %v", resp.StatusCode, http.StatusOK)
|
||
}
|
||
}
|
||
|
||
// TestMiddleware 测试中间件
|
||
func TestMiddleware(t *testing.T) {
|
||
// 测试CORS中间件
|
||
req, err := http.NewRequest("OPTIONS", "/api/users", nil)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
rr := httptest.NewRecorder()
|
||
|
||
// 创建带中间件的处理器
|
||
handler := server.CORSMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
w.WriteHeader(http.StatusOK)
|
||
}))
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
// 检查CORS头
|
||
if origin := rr.Header().Get("Access-Control-Allow-Origin"); origin != "*" {
|
||
t.Errorf("期望CORS Origin为 '*', 实际为 '%s'", origin)
|
||
}
|
||
|
||
if methods := rr.Header().Get("Access-Control-Allow-Methods"); methods == "" {
|
||
t.Error("应该设置Access-Control-Allow-Methods头")
|
||
}
|
||
}
|
||
|
||
// BenchmarkHealthHandler 健康检查处理器基准测试
|
||
func BenchmarkHealthHandler(b *testing.B) {
|
||
req, _ := http.NewRequest("GET", "/health", nil)
|
||
|
||
b.ResetTimer()
|
||
for i := 0; i < b.N; i++ {
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.HealthHandler)
|
||
handler.ServeHTTP(rr, req)
|
||
}
|
||
}
|
||
|
||
// BenchmarkGetUsersHandler 获取用户列表处理器基准测试
|
||
func BenchmarkGetUsersHandler(b *testing.B) {
|
||
req, _ := http.NewRequest("GET", "/api/users", nil)
|
||
|
||
b.ResetTimer()
|
||
for i := 0; i < b.N; i++ {
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.GetUsersHandler)
|
||
handler.ServeHTTP(rr, req)
|
||
}
|
||
}
|
||
|
||
// ExampleHealthHandler 健康检查处理器示例
|
||
func ExampleHealthHandler() {
|
||
req, _ := http.NewRequest("GET", "/health", nil)
|
||
rr := httptest.NewRecorder()
|
||
handler := http.HandlerFunc(server.HealthHandler)
|
||
|
||
handler.ServeHTTP(rr, req)
|
||
|
||
fmt.Printf("Status: %d", rr.Code)
|
||
// Output: Status: 200
|
||
}
|