/* 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 }