Go 内置标准库net/http/httptest核心用途用于测试net/http构建的HTTP服务如API接口、Web服务等它可以模拟HTTP请求发送和HTTP响应的接收无需启动真实的HTTP服务器即可完成接口测试极大提升了测试的便捷性和执行效率优点无需启动真实服务器无需调用http.ListenAndServe启动端口监听直接测试 HTTP 处理器Handler/HandlerFunc测试执行更高效。脱离网络依赖模拟 HTTP 请求与响应的完整生命周期不受网络波动、端口占用等外部因素影响测试结果稳定可复现。精准捕获响应细节可完整获取响应状态码、响应头、响应体等所有信息便于精准断言验证。支持两种核心测试场景测试 HTTP 处理器直接调用ServeHTTP最常用启动临时测试服务器模拟真实服务端用于客户端测试或集成测试1.安装内置工具可以直接使用2.使用示例相关代码在gitee代码仓库的示例代码中仓库地址请看博客开头blog.gopackage httptest_demoimport (errorsfmtionet/http)func SearchHttp(targetURL string) (interface{}, error) {resp, err : http.Get(targetURL)if err ! nil {errMsg : fmt.Sprintf(发送 GET 请求失败%v, err)fmt.Println(errMsg)return nil, errors.New(errMsg)}defer resp.Body.Close()if resp.StatusCode ! http.StatusOK {errMsg : fmt.Sprintf(请求失败状态码%d状态信息%s, resp.StatusCode, resp.Status)fmt.Println(errMsg)return nil, errors.New(errMsg)}bodyBytes, _ : io.ReadAll(resp.Body)return string(bodyBytes), nil}blog_test.gopackage httptest_demoimport (net/httpnet/http/httpteststringstesting)func TestSearchHttp(t *testing.T) {// --------------- 1. 定义所有测试场景的表驱动用例循环遍历执行 ---------------testCases : []struct {name string // 用例名称prepareFunc func() string // 前置准备创建模拟服务器/构造URL返回待请求的URLexpectedErr bool // 是否预期返回错误errContains string // 预期错误信息包含的关键字非空则验证expectedNonEmpty bool // 正常场景下是否预期返回非空字符串}{// 场景1正常请求200 OK响应体正常{name: 正常请求-状态码200,prepareFunc: func() string {// 启动模拟HTTP服务器返回200和测试响应体mockServer : httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {mockBody : !DOCTYPE htmlhtmltitle百度一下/title/htmlw.WriteHeader(http.StatusOK)_, _ w.Write([]byte(mockBody))}))// 关键将mockServer放入测试上下文确保后续能关闭避免资源泄露t.Cleanup(func() { mockServer.Close() })return mockServer.URL},expectedErr: false,errContains: ,expectedNonEmpty: true,},// 场景2请求失败无效URL模拟网络异常{name: 异常场景-无效URL请求失败,prepareFunc: func() string {// 返回一个无效的URL触发http.Get请求失败return http://invalid-xxx-url-12345/},expectedErr: true,errContains: 发送 GET 请求失败,expectedNonEmpty: false,},// 场景3状态码非200模拟404 Not Found{name: 异常场景-状态码404,prepareFunc: func() string {// 启动模拟HTTP服务器返回404状态码mockServer : httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(http.StatusNotFound)_, _ w.Write([]byte(页面不存在))}))t.Cleanup(func() { mockServer.Close() })return mockServer.URL},expectedErr: true,errContains: 请求失败状态码404,expectedNonEmpty: false,},// 场景4状态码非200模拟500服务器内部错误{name: 异常场景-状态码500,prepareFunc: func() string {// 启动模拟HTTP服务器返回500状态码mockServer : httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(http.StatusInternalServerError)_, _ w.Write([]byte(服务器内部错误))}))t.Cleanup(func() { mockServer.Close() })return mockServer.URL},expectedErr: true,errContains: 请求失败状态码500,expectedNonEmpty: false,},}// --------------- 2. 循环遍历所有测试用例统一执行验证 ---------------for _, tc : range testCases {// 循环内使用t.Run创建子用例便于精准定位失败场景不影响其他用例t.Run(tc.name, func(t *testing.T) {// 步骤1执行前置准备获取待请求的URLtargetURL : tc.prepareFunc()// 步骤2调用被测函数result, err : SearchHttp(targetURL)// 步骤3统一断言验证// 3.1 验证错误是否符合预期if (err ! nil) ! tc.expectedErr {t.Fatalf(错误预期不符预期是否错误[%t]实际是否错误[%t]错误信息[%v],tc.expectedErr, err ! nil, err)}// 3.2 若预期错误验证错误信息是否包含指定关键字if tc.expectedErr tc.errContains ! {if !strings.Contains(err.Error(), tc.errContains) {t.Errorf(错误信息不符预期包含[%s]实际错误[%v], tc.errContains, err)}}// 3.3 验证返回值是否符合预期if tc.expectedErr {// 异常场景预期返回nilif result ! nil {t.Errorf(异常场景预期返回nil实际返回[%v]类型[%T], result, result)}} else {// 正常场景验证返回值是string类型且非空若预期非空resultStr, ok : result.(string)if !ok {t.Fatalf(正常场景预期返回string类型实际返回[%T], result)}if tc.expectedNonEmpty len(resultStr) 0 {t.Error(正常场景预期返回非空字符串实际返回空字符串)}}})}}命令行执行命令